From 24edf4b8989a60f108982ee44590df856a8fc9b2 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 9 May 2005 17:50:11 +0000 Subject: [PATCH] bitkeeper revision 1.1389.10.1 (427fa2d3ZV92f_ErvLuIzWbV1f67QA) Phase 1 of upgrading platform code to be derived from Linux 2.6.11 rather than 2.4.x. Signed-off-by: Keir Fraser --- .rootkeys | 30 +- xen/arch/x86/Makefile | 1 + xen/arch/x86/Rules.mk | 4 +- xen/arch/x86/acpi.c | 729 -------- xen/arch/x86/acpi/boot.c | 912 ++++++++++ xen/arch/x86/apic.c | 19 +- xen/arch/x86/i8259.c | 10 +- xen/arch/x86/io_apic.c | 1598 ++++++++++------- xen/arch/x86/irq.c | 1 - xen/arch/x86/microcode.c | 7 - xen/arch/x86/mpparse.c | 706 +++----- xen/arch/x86/mtrr/main.c | 1 + xen/arch/x86/nmi.c | 10 +- xen/arch/x86/physdev.c | 2 - xen/arch/x86/smpboot.c | 32 +- xen/arch/x86/x86_32/asm-offsets.c | 2 +- xen/arch/x86/x86_32/mm.c | 2 +- xen/arch/x86/x86_32/traps.c | 8 +- xen/arch/x86/x86_64/mm.c | 2 +- xen/common/bitmap.c | 365 ++++ xen/common/xmalloc.c | 2 +- xen/drivers/acpi/tables.c | 61 +- xen/include/acpi/acconfig.h | 31 +- xen/include/acpi/acexcep.h | 10 +- xen/include/acpi/acglobal.h | 81 +- xen/include/acpi/achware.h | 43 +- xen/include/acpi/aclocal.h | 54 +- xen/include/acpi/acmacros.h | 63 +- xen/include/acpi/acobject.h | 31 +- xen/include/acpi/acoutput.h | 4 +- xen/include/acpi/acpi.h | 2 +- xen/include/acpi/acpi_bus.h | 69 +- xen/include/acpi/acpi_drivers.h | 284 +-- xen/include/acpi/acpiosxf.h | 38 +- xen/include/acpi/acpixf.h | 45 +- xen/include/acpi/acstruct.h | 27 +- xen/include/acpi/actbl.h | 33 +- xen/include/acpi/actbl1.h | 2 +- xen/include/acpi/actbl2.h | 94 +- xen/include/acpi/actypes.h | 149 +- xen/include/acpi/acutils.h | 43 +- xen/include/acpi/platform/acenv.h | 23 +- xen/include/acpi/platform/acgcc.h | 4 +- xen/include/acpi/platform/aclinux.h | 6 +- xen/include/asm-ia64/config.h | 8 - xen/include/asm-x86/apic.h | 56 +- xen/include/asm-x86/apicdef.h | 279 ++- xen/include/asm-x86/config.h | 4 + xen/include/asm-x86/domain.h | 2 + xen/include/asm-x86/fixmap.h | 33 +- xen/include/asm-x86/io_apic.h | 148 +- xen/include/asm-x86/io_ports.h | 30 - xen/include/asm-x86/irq.h | 52 +- xen/include/asm-x86/mach-default/apm.h | 75 + xen/include/asm-x86/mach-default/bios_ebda.h | 15 + xen/include/asm-x86/mach-default/do_timer.h | 85 + xen/include/asm-x86/mach-default/entry_arch.h | 34 + xen/include/asm-x86/mach-default/io_ports.h | 30 + .../asm-x86/mach-default/irq_vectors.h | 96 + .../asm-x86/mach-default/irq_vectors_limits.h | 21 + xen/include/asm-x86/mach-default/mach_apic.h | 133 ++ .../asm-x86/mach-default/mach_apicdef.h | 13 + xen/include/asm-x86/mach-default/mach_ipi.h | 30 + .../asm-x86/mach-default/mach_mpparse.h | 28 + .../asm-x86/mach-default/mach_mpspec.h | 8 + .../asm-x86/mach-default/mach_reboot.h | 30 + xen/include/asm-x86/mach-default/mach_time.h | 122 ++ xen/include/asm-x86/mach-default/mach_timer.h | 48 + xen/include/asm-x86/mach-default/mach_traps.h | 29 + .../asm-x86/mach-default/mach_wakecpu.h | 41 + .../asm-x86/mach-default/pci-functions.h | 19 + .../asm-x86/mach-default/setup_arch_post.h | 40 + .../asm-x86/mach-default/setup_arch_pre.h | 5 + .../asm-x86/mach-default/smpboot_hooks.h | 44 + xen/include/asm-x86/mach_apic.h | 32 - xen/include/asm-x86/mpspec.h | 280 +-- xen/include/asm-x86/mpspec_def.h | 188 ++ xen/include/asm-x86/page.h | 2 - xen/include/asm-x86/processor.h | 15 +- xen/include/asm-x86/smp.h | 92 +- xen/include/asm-x86/smpboot.h | 116 -- xen/include/asm-x86/system.h | 1 + xen/include/asm-x86/time.h | 2 +- xen/include/xen/acpi.h | 126 +- xen/include/xen/bitmap.h | 249 +++ xen/include/xen/bitops.h | 129 ++ xen/include/xen/config.h | 6 +- xen/include/xen/cpumask.h | 25 + xen/include/xen/irq.h | 3 +- xen/include/xen/smp.h | 19 + xen/include/xen/spinlock.h | 3 + xen/include/xen/types.h | 6 + 92 files changed, 5449 insertions(+), 3043 deletions(-) delete mode 100644 xen/arch/x86/acpi.c create mode 100644 xen/arch/x86/acpi/boot.c create mode 100644 xen/common/bitmap.c delete mode 100644 xen/include/asm-x86/io_ports.h create mode 100644 xen/include/asm-x86/mach-default/apm.h create mode 100644 xen/include/asm-x86/mach-default/bios_ebda.h create mode 100644 xen/include/asm-x86/mach-default/do_timer.h create mode 100644 xen/include/asm-x86/mach-default/entry_arch.h create mode 100644 xen/include/asm-x86/mach-default/io_ports.h create mode 100644 xen/include/asm-x86/mach-default/irq_vectors.h create mode 100644 xen/include/asm-x86/mach-default/irq_vectors_limits.h create mode 100644 xen/include/asm-x86/mach-default/mach_apic.h create mode 100644 xen/include/asm-x86/mach-default/mach_apicdef.h create mode 100644 xen/include/asm-x86/mach-default/mach_ipi.h create mode 100644 xen/include/asm-x86/mach-default/mach_mpparse.h create mode 100644 xen/include/asm-x86/mach-default/mach_mpspec.h create mode 100644 xen/include/asm-x86/mach-default/mach_reboot.h create mode 100644 xen/include/asm-x86/mach-default/mach_time.h create mode 100644 xen/include/asm-x86/mach-default/mach_timer.h create mode 100644 xen/include/asm-x86/mach-default/mach_traps.h create mode 100644 xen/include/asm-x86/mach-default/mach_wakecpu.h create mode 100644 xen/include/asm-x86/mach-default/pci-functions.h create mode 100644 xen/include/asm-x86/mach-default/setup_arch_post.h create mode 100644 xen/include/asm-x86/mach-default/setup_arch_pre.h create mode 100644 xen/include/asm-x86/mach-default/smpboot_hooks.h delete mode 100644 xen/include/asm-x86/mach_apic.h create mode 100644 xen/include/asm-x86/mpspec_def.h create mode 100644 xen/include/xen/bitmap.h create mode 100644 xen/include/xen/bitops.h create mode 100644 xen/include/xen/cpumask.h diff --git a/.rootkeys b/.rootkeys index cfb01fda7d..c3afd372dd 100644 --- a/.rootkeys +++ b/.rootkeys @@ -1185,7 +1185,7 @@ 427664f5eygrc3nEhI3RKf0Y37PzyA xen/arch/ia64/xentime.c 3ddb79bcZbRBzT3elFWSX7u6NtMagQ xen/arch/x86/Makefile 3ddb79bcBQF85CfLS4i1WGZ4oLLaCA xen/arch/x86/Rules.mk -3e5636e5FAYZ5_vQnmgwFJfSdmO5Mw xen/arch/x86/acpi.c +3e5636e5FAYZ5_vQnmgwFJfSdmO5Mw xen/arch/x86/acpi/boot.c 3ddb79bcsjinG9k1KcvbVBuas1R2dA xen/arch/x86/apic.c 42360b3244-Q6BpEKhR_A1YtG1wPNQ xen/arch/x86/audit.c 3ddb79c4yGZ7_22QAFFwPzqP4NSHwA xen/arch/x86/boot/mkelf32.c @@ -1247,6 +1247,7 @@ 422f27c8J9DQfCpegccMid59XhSmGA xen/arch/x86/x86_emulate.c 3ddb79bdff-gj-jFGKjOejeHLqL8Lg xen/common/Makefile 3e397e66AyyD5fYraAySWuwi9uqSXg xen/common/ac_timer.c +427fa2d0J0LU2s5oKbsM0nTZ2iyd2Q xen/common/bitmap.c 3ddb79bdLX_P6iB7ILiblRLWvebapg xen/common/dom0_ops.c 3e6377e4i0c9GtKN65e99OtRbw3AZw xen/common/dom_mem_ops.c 3ddb79bdYO5D8Av12NHqPeSviav7cg xen/common/domain.c @@ -1341,13 +1342,33 @@ 4204e7acwXDo-5iAAiO2eQbtDeYZXA xen/include/asm-x86/init.h 3ddb79c3fQ_O3o5NHK2N8AJdk0Ea4Q xen/include/asm-x86/io.h 3ddb79c2TKeScYHQZreTdHqYNLbehQ xen/include/asm-x86/io_apic.h -42605109qxLSrHVE2SRhGXmgk907iw xen/include/asm-x86/io_ports.h 3ddb79c2L7rTlFzazOLW1XuSZefpFw xen/include/asm-x86/irq.h 404f1b93OjLO4bFfBXYNaJdIqlNz-Q xen/include/asm-x86/ldt.h -4260510aYPj2kr6rMbBfMxcvvmXndQ xen/include/asm-x86/mach_apic.h +427fa2d0m8MOSSXT13zgb-q0fGA_Dw xen/include/asm-x86/mach-default/apm.h +427fa2d0suK9Av7vsAXhsQxZjqpc_Q xen/include/asm-x86/mach-default/bios_ebda.h +427fa2d0yC3KzLozoeK3Xa3uGVfIdw xen/include/asm-x86/mach-default/do_timer.h +427fa2d0bWQkR1mW5OBYxn07AN-bDw xen/include/asm-x86/mach-default/entry_arch.h +427fa2d0-SWcuwbdSypo4953bc2JdQ xen/include/asm-x86/mach-default/io_ports.h +427fa2d0eyAl7LAeO-SVV4IW7lZPGQ xen/include/asm-x86/mach-default/irq_vectors.h +427fa2d0df7VWG4KKpnKbKR2Cbd1_w xen/include/asm-x86/mach-default/irq_vectors_limits.h +4260510aYPj2kr6rMbBfMxcvvmXndQ xen/include/asm-x86/mach-default/mach_apic.h +427fa2d0I3FWjE2tWdOhlEOJn7stcg xen/include/asm-x86/mach-default/mach_apicdef.h +427fa2d093fDS2gOBLcl7Yndzl7HmA xen/include/asm-x86/mach-default/mach_ipi.h +427fa2d0Y7bD35d-FvDAeiJDIdRw2A xen/include/asm-x86/mach-default/mach_mpparse.h +427fa2d0aLQgE9e1GY9ZP5jrMOC8pQ xen/include/asm-x86/mach-default/mach_mpspec.h +427fa2d0fJ5nNn5ydJuOaZIL6F2fjQ xen/include/asm-x86/mach-default/mach_reboot.h +427fa2d0VlN555TE68TjKMsrOoFXNA xen/include/asm-x86/mach-default/mach_time.h +427fa2d0C0jWTKYjy7WJjGKeujSpSg xen/include/asm-x86/mach-default/mach_timer.h +427fa2d0UXLiS1scpNrK26ZT6Oes3g xen/include/asm-x86/mach-default/mach_traps.h +427fa2d0OfglYyfpDTD5DII4M0uZRw xen/include/asm-x86/mach-default/mach_wakecpu.h +427fa2d0_OBPxdi5Qo04JWgZhz7BFA xen/include/asm-x86/mach-default/pci-functions.h +427fa2d0mrTtXrliqDfLuJc5LLVXaA xen/include/asm-x86/mach-default/setup_arch_post.h +427fa2d0Uoo7gC61Kep6Yy7Os367Hg xen/include/asm-x86/mach-default/setup_arch_pre.h +427fa2d1EKnA8zCq2QLHiGOUqOgszg xen/include/asm-x86/mach-default/smpboot_hooks.h 3ddb79c3I98vWcQR8xEo34JMJ4Ahyw xen/include/asm-x86/mc146818rtc.h 40ec25fd7cSvbP7Biw91zaU_g0xsEQ xen/include/asm-x86/mm.h 3ddb79c3n_UbPuxlkNxvvLycClIkxA xen/include/asm-x86/mpspec.h +427fa2d1eJRenftJJnRyLsHKl1ghtA xen/include/asm-x86/mpspec_def.h 3ddb79c2wa0dA_LGigxOelSGbJ284Q xen/include/asm-x86/msr.h 41aaf567Mi3OishhvrCtET1y-mxQBg xen/include/asm-x86/mtrr.h 41a61536MFhNalgbVmYGXAhQsPTZNw xen/include/asm-x86/multicall.h @@ -1409,11 +1430,14 @@ 3ddb79c25UE59iu4JJcbRalx95mvcg xen/include/public/xen.h 3e397e66m2tO3s-J8Jnr7Ws_tGoPTg xen/include/xen/ac_timer.h 40715b2epYl2jBbxzz9CI2rgIca7Zg xen/include/xen/acpi.h +427fa2d1wyoVbvCyZRLposYjA_D_4g xen/include/xen/bitmap.h +427fa2d1ItcC_yWuBUkhc7adedP5ow xen/include/xen/bitops.h 3ddb79c0c0cX_DZE209-Bb-Rx1v-Aw xen/include/xen/cache.h 41f2cea7Yna7xc0X9fyavIjoSFFeVg xen/include/xen/compile.h.in 3f840f12CkbYSlwMrY2S11Mpyxg7Nw xen/include/xen/compiler.h 3ddb79c259jh8hE7vre_8NuE7nwNSA xen/include/xen/config.h 3eb165e0eawr3R-p2ZQtSdLWtLRN_A xen/include/xen/console.h +427fa2d1bQCWgEQqTTh5MjG4MPEH9g xen/include/xen/cpumask.h 3ddb79c1V44RD26YqCUm-kqIupM37A xen/include/xen/ctype.h 3ddb79c05DdHQ0UxX_jKsXdR4QlMCA xen/include/xen/delay.h 40f2b4a2hC3HtChu-ArD8LyojxWMjg xen/include/xen/domain.h diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile index 42d828f7f5..ddb605e9cf 100644 --- a/xen/arch/x86/Makefile +++ b/xen/arch/x86/Makefile @@ -3,6 +3,7 @@ include $(BASEDIR)/Rules.mk OBJS += $(patsubst %.S,%.o,$(wildcard $(TARGET_SUBARCH)/*.S)) OBJS += $(patsubst %.c,%.o,$(wildcard $(TARGET_SUBARCH)/*.c)) +OBJS += $(patsubst %.c,%.o,$(wildcard acpi/*.c)) OBJS += $(patsubst %.c,%.o,$(wildcard mtrr/*.c)) OBJS := $(subst $(TARGET_SUBARCH)/asm-offsets.o,,$(OBJS)) diff --git a/xen/arch/x86/Rules.mk b/xen/arch/x86/Rules.mk index 915a646bed..f21be04704 100644 --- a/xen/arch/x86/Rules.mk +++ b/xen/arch/x86/Rules.mk @@ -2,8 +2,8 @@ # x86-specific definitions CFLAGS += -nostdinc -fno-builtin -fno-common -fno-strict-aliasing -CFLAGS += -iwithprefix include -Wall -Werror -pipe -CFLAGS += -I$(BASEDIR)/include -Wno-pointer-arith -Wredundant-decls +CFLAGS += -iwithprefix include -Wall -Werror -Wno-pointer-arith -pipe +CFLAGS += -I$(BASEDIR)/include -I$(BASEDIR)/include/asm-x86/mach-default ifeq ($(optimize),y) CFLAGS += -O3 -fomit-frame-pointer diff --git a/xen/arch/x86/acpi.c b/xen/arch/x86/acpi.c deleted file mode 100644 index 4d3cc212b1..0000000000 --- a/xen/arch/x86/acpi.c +++ /dev/null @@ -1,729 +0,0 @@ -/* - * acpi.c - Architecture-Specific Low-Level ACPI Support - * - * Copyright (C) 2001, 2002 Paul Diefenbaugh - * Copyright (C) 2001 Jun Nakajima - * Copyright (C) 2001 Patrick Mochel - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#define PREFIX "ACPI: " - -int acpi_lapic; -int acpi_ioapic; -int acpi_strict; - -acpi_interrupt_flags acpi_sci_flags __initdata; -int acpi_sci_override_gsi __initdata; -/* -------------------------------------------------------------------------- - Boot-time Configuration - -------------------------------------------------------------------------- */ - -int acpi_noirq __initdata = 0; /* skip ACPI IRQ initialization */ -int acpi_ht __initdata = 1; /* enable HT */ - -enum acpi_irq_model_id acpi_irq_model; - - -/* - * Temporarily use the virtual area starting from FIX_IO_APIC_BASE_END, - * to map the target physical address. The problem is that set_fixmap() - * provides a single page, and it is possible that the page is not - * sufficient. - * By using this area, we can map up to MAX_IO_APICS pages temporarily, - * i.e. until the next __va_range() call. - * - * Important Safety Note: The fixed I/O APIC page numbers are *subtracted* - * from the fixed base. That's why we start at FIX_IO_APIC_BASE_END and - * count idx down while incrementing the phys address. - */ -char *__acpi_map_table(unsigned long phys, unsigned long size) -{ - unsigned long base, offset, mapped_size; - int idx; - - if (phys + size < 8*1024*1024) - return __va(phys); - - offset = phys & (PAGE_SIZE - 1); - mapped_size = PAGE_SIZE - offset; - set_fixmap(FIX_ACPI_END, phys); - base = fix_to_virt(FIX_ACPI_END); - - /* - * Most cases can be covered by the below. - */ - idx = FIX_ACPI_END; - while (mapped_size < size) { - if (--idx < FIX_ACPI_BEGIN) - return 0; /* cannot handle this */ - phys += PAGE_SIZE; - set_fixmap(idx, phys); - mapped_size += PAGE_SIZE; - } - - return ((char *) base + offset); -} - - -#ifdef CONFIG_X86_LOCAL_APIC - -static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE; - - -static int __init -acpi_parse_madt ( - unsigned long phys_addr, - unsigned long size) -{ - struct acpi_table_madt *madt = NULL; - - if (!phys_addr || !size) - return -EINVAL; - - madt = (struct acpi_table_madt *) __acpi_map_table(phys_addr, size); - if (!madt) { - printk(KERN_WARNING PREFIX "Unable to map MADT\n"); - return -ENODEV; - } - - if (madt->lapic_address) - acpi_lapic_addr = (u64) madt->lapic_address; - - printk(KERN_INFO PREFIX "Local APIC address 0x%08x\n", - madt->lapic_address); - - detect_clustered_apic(madt->header.oem_id, madt->header.oem_table_id); - - return 0; -} - - -static int __init -acpi_parse_lapic ( - acpi_table_entry_header *header) -{ - struct acpi_table_lapic *processor = NULL; - - processor = (struct acpi_table_lapic*) header; - if (!processor) - return -EINVAL; - - acpi_table_print_madt_entry(header); - - mp_register_lapic ( - processor->id, /* APIC ID */ - processor->flags.enabled); /* Enabled? */ - - return 0; -} - - -static int __init -acpi_parse_lapic_addr_ovr ( - acpi_table_entry_header *header) -{ - struct acpi_table_lapic_addr_ovr *lapic_addr_ovr = NULL; - - lapic_addr_ovr = (struct acpi_table_lapic_addr_ovr*) header; - if (!lapic_addr_ovr) - return -EINVAL; - - acpi_lapic_addr = lapic_addr_ovr->address; - - return 0; -} - -static int __init -acpi_parse_lapic_nmi ( - acpi_table_entry_header *header) -{ - struct acpi_table_lapic_nmi *lapic_nmi = NULL; - - lapic_nmi = (struct acpi_table_lapic_nmi*) header; - if (!lapic_nmi) - return -EINVAL; - - acpi_table_print_madt_entry(header); - - if (lapic_nmi->lint != 1) - printk(KERN_WARNING PREFIX "NMI not connected to LINT 1!\n"); - - return 0; -} - -#endif /*CONFIG_X86_LOCAL_APIC*/ - -#if defined(CONFIG_X86_IO_APIC) /*&& defined(CONFIG_ACPI_INTERPRETER)*/ - -static int __init -acpi_parse_ioapic ( - acpi_table_entry_header *header) -{ - struct acpi_table_ioapic *ioapic = NULL; - - ioapic = (struct acpi_table_ioapic*) header; - if (!ioapic) - return -EINVAL; - - acpi_table_print_madt_entry(header); - - mp_register_ioapic ( - ioapic->id, - ioapic->address, - ioapic->global_irq_base); - - return 0; -} - -#ifdef CONFIG_ACPI_INTERPRETER -/* - * Parse Interrupt Source Override for the ACPI SCI - */ -static void -acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger) -{ - if (trigger == 0) /* compatible SCI trigger is level */ - trigger = 3; - - if (polarity == 0) /* compatible SCI polarity is low */ - polarity = 3; - - /* Command-line over-ride via acpi_sci= */ - if (acpi_sci_flags.trigger) - trigger = acpi_sci_flags.trigger; - - if (acpi_sci_flags.polarity) - polarity = acpi_sci_flags.polarity; - - /* - * mp_config_acpi_legacy_irqs() already setup IRQs < 16 - * If GSI is < 16, this will update its flags, - * else it will create a new mp_irqs[] entry. - */ - mp_override_legacy_irq(gsi, polarity, trigger, gsi); - - /* - * stash over-ride to indicate we've been here - * and for later update of acpi_fadt - */ - acpi_sci_override_gsi = gsi; - return; -} -#endif - -static int __init -acpi_parse_fadt(unsigned long phys, unsigned long size) -{ - struct fadt_descriptor_rev2 *fadt =0; - - fadt = (struct fadt_descriptor_rev2*) __acpi_map_table(phys,size); - if (!fadt) { - printk(KERN_WARNING PREFIX "Unable to map FADT\n"); - return 0; - } - -#ifdef CONFIG_ACPI_INTERPRETER - /* initialize sci_int early for INT_SRC_OVR MADT parsing */ - acpi_fadt.sci_int = fadt->sci_int; -#endif - - return 0; -} - - -static int __init -acpi_parse_int_src_ovr ( - acpi_table_entry_header *header) -{ - struct acpi_table_int_src_ovr *intsrc = NULL; - - intsrc = (struct acpi_table_int_src_ovr*) header; - if (!intsrc) - return -EINVAL; - - acpi_table_print_madt_entry(header); - -#ifdef CONFIG_ACPI_INTERPRETER - if (intsrc->bus_irq == acpi_fadt.sci_int) { - acpi_sci_ioapic_setup(intsrc->global_irq, - intsrc->flags.polarity, intsrc->flags.trigger); - return 0; - } -#endif - - mp_override_legacy_irq ( - intsrc->bus_irq, - intsrc->flags.polarity, - intsrc->flags.trigger, - intsrc->global_irq); - - return 0; -} - - -static int __init -acpi_parse_nmi_src ( - acpi_table_entry_header *header) -{ - struct acpi_table_nmi_src *nmi_src = NULL; - - nmi_src = (struct acpi_table_nmi_src*) header; - if (!nmi_src) - return -EINVAL; - - acpi_table_print_madt_entry(header); - - /* TBD: Support nimsrc entries? */ - - return 0; -} - -#endif /*CONFIG_X86_IO_APIC && CONFIG_ACPI_INTERPRETER*/ - - -static unsigned long __init -acpi_scan_rsdp ( - unsigned long start, - unsigned long length) -{ - unsigned long offset = 0; - unsigned long sig_len = sizeof("RSD PTR ") - 1; - - /* - * Scan all 16-byte boundaries of the physical memory region for the - * RSDP signature. - */ - for (offset = 0; offset < length; offset += 16) { - if (strncmp((char *) (start + offset), "RSD PTR ", sig_len)) - continue; - return (start + offset); - } - - return 0; -} - - -unsigned long __init -acpi_find_rsdp (void) -{ - unsigned long rsdp_phys = 0; - - /* - * Scan memory looking for the RSDP signature. First search EBDA (low - * memory) paragraphs and then search upper memory (E0000-FFFFF). - */ - rsdp_phys = acpi_scan_rsdp (0, 0x400); - if (!rsdp_phys) - rsdp_phys = acpi_scan_rsdp (0xE0000, 0x20000); - - return rsdp_phys; -} - - -/* - * acpi_boot_init() - * called from setup_arch(), always. - * 1. maps ACPI tables for later use - * 2. enumerates lapics - * 3. enumerates io-apics - * - * side effects: - * acpi_lapic = 1 if LAPIC found - * acpi_ioapic = 1 if IOAPIC found - * if (acpi_lapic && acpi_ioapic) smp_found_config = 1; - * if acpi_blacklisted() disable_acpi() - * acpi_irq_model=... - * ... - * - * return value: (currently ignored) - * 0: success - * !0: failure - */ -int __init -acpi_boot_init (void) -{ - int result = 0; - - if (acpi_disabled && !acpi_ht) - return(1); - - /* - * The default interrupt routing model is PIC (8259). This gets - * overriden if IOAPICs are enumerated (below). - */ - acpi_irq_model = ACPI_IRQ_MODEL_PIC; - - /* - * Initialize the ACPI boot-time table parser. - */ - result = acpi_table_init(); - if (result) { - disable_acpi(); - return result; - } - - result = acpi_blacklisted(); - if (result) { - printk(KERN_NOTICE PREFIX "BIOS listed in blacklist, disabling ACPI support\n"); - disable_acpi(); - return result; - } - -#ifdef CONFIG_X86_LOCAL_APIC - - /* - * MADT - * ---- - * Parse the Multiple APIC Description Table (MADT), if exists. - * Note that this table provides platform SMP configuration - * information -- the successor to MPS tables. - */ - - result = acpi_table_parse(ACPI_APIC, acpi_parse_madt); - if (!result) { - return 0; - } - else if (result < 0) { - printk(KERN_ERR PREFIX "Error parsing MADT\n"); - return result; - } - else if (result > 1) - printk(KERN_WARNING PREFIX "Multiple MADT tables exist\n"); - - /* - * Local APIC - * ---------- - * Note that the LAPIC address is obtained from the MADT (32-bit value) - * and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value). - */ - - result = acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR, acpi_parse_lapic_addr_ovr); - if (result < 0) { - printk(KERN_ERR PREFIX "Error parsing LAPIC address override entry\n"); - return result; - } - - mp_register_lapic_address(acpi_lapic_addr); - - result = acpi_table_parse_madt(ACPI_MADT_LAPIC, acpi_parse_lapic); - if (!result) { - printk(KERN_ERR PREFIX "No LAPIC entries present\n"); - /* TBD: Cleanup to allow fallback to MPS */ - return -ENODEV; - } - else if (result < 0) { - printk(KERN_ERR PREFIX "Error parsing LAPIC entry\n"); - /* TBD: Cleanup to allow fallback to MPS */ - return result; - } - - result = acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi); - if (result < 0) { - printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n"); - /* TBD: Cleanup to allow fallback to MPS */ - return result; - } - - acpi_lapic = 1; - -#endif /*CONFIG_X86_LOCAL_APIC*/ - -#if defined(CONFIG_X86_IO_APIC) /*&& defined(CONFIG_ACPI_INTERPRETER)*/ - - /* - * I/O APIC - * -------- - */ - -#if 0 - /* - * ACPI interpreter is required to complete interrupt setup, - * so if it is off, don't enumerate the io-apics with ACPI. - * If MPS is present, it will handle them, - * otherwise the system will stay in PIC mode - */ - if (acpi_disabled || acpi_noirq) { - return 1; - } -#endif - - /* - * if "noapic" boot option, don't look for IO-APICs - */ - if (ioapic_setup_disabled()) { - printk(KERN_INFO PREFIX "Skipping IOAPIC probe " - "due to 'noapic' option.\n"); - return 1; - } - - - result = acpi_table_parse_madt(ACPI_MADT_IOAPIC, acpi_parse_ioapic); - if (!result) { - printk(KERN_ERR PREFIX "No IOAPIC entries present\n"); - return -ENODEV; - } - else if (result < 0) { - printk(KERN_ERR PREFIX "Error parsing IOAPIC entry\n"); - return result; - } - - /* Build a default routing table for legacy (ISA) interrupts. */ - mp_config_acpi_legacy_irqs(); - - /* Record sci_int for use when looking for MADT sci_int override */ - acpi_table_parse(ACPI_FADT, acpi_parse_fadt); - - result = acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr); - if (result < 0) { - printk(KERN_ERR PREFIX "Error parsing interrupt source overrides entry\n"); - /* TBD: Cleanup to allow fallback to MPS */ - return result; - } - -#ifdef CONFIG_ACPI_INTERPRETER - /* - * If BIOS did not supply an INT_SRC_OVR for the SCI - * pretend we got one so we can set the SCI flags. - */ - if (!acpi_sci_override_gsi) - acpi_sci_ioapic_setup(acpi_fadt.sci_int, 0, 0); -#endif - - result = acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src); - if (result < 0) { - printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n"); - /* TBD: Cleanup to allow fallback to MPS */ - return result; - } - - acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC; - - acpi_irq_balance_set(NULL); - - acpi_ioapic = 1; - - if (acpi_lapic && acpi_ioapic) - smp_found_config = 1; - -#endif /*CONFIG_X86_IO_APIC && CONFIG_ACPI_INTERPRETER*/ - - return 0; -} - - -#ifdef CONFIG_ACPI_BUS -/* - * acpi_pic_sci_set_trigger() - * - * use ELCR to set PIC-mode trigger type for SCI - * - * If a PIC-mode SCI is not recognized or gives spurious IRQ7's - * it may require Edge Trigger -- use "acpi_sci=edge" - * - * Port 0x4d0-4d1 are ECLR1 and ECLR2, the Edge/Level Control Registers - * for the 8259 PIC. bit[n] = 1 means irq[n] is Level, otherwise Edge. - * ECLR1 is IRQ's 0-7 (IRQ 0, 1, 2 must be 0) - * ECLR2 is IRQ's 8-15 (IRQ 8, 13 must be 0) - */ - -void __init -acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger) -{ - unsigned char mask = 1 << (irq & 7); - unsigned int port = 0x4d0 + (irq >> 3); - unsigned char val = inb(port); - - - printk(PREFIX "IRQ%d SCI:", irq); - if (!(val & mask)) { - printk(" Edge"); - - if (trigger == 3) { - printk(" set to Level"); - outb(val | mask, port); - } - } else { - printk(" Level"); - - if (trigger == 1) { - printk(" set to Edge"); - outb(val & ~mask, port); - } - } - printk(" Trigger.\n"); -} - -#endif /* CONFIG_ACPI_BUS */ - - -/* -------------------------------------------------------------------------- - Low-Level Sleep Support - -------------------------------------------------------------------------- */ - -#ifdef CONFIG_ACPI_SLEEP - -#define DEBUG - -#ifdef DEBUG -#include -#endif - -/* address in low memory of the wakeup routine. */ -unsigned long acpi_wakeup_address = 0; - -/* new page directory that we will be using */ -static pmd_t *pmd; - -/* saved page directory */ -static pmd_t saved_pmd; - -/* page which we'll use for the new page directory */ -static pte_t *ptep; - -extern unsigned long FASTCALL(acpi_copy_wakeup_routine(unsigned long)); - -/* - * acpi_create_identity_pmd - * - * Create a new, identity mapped pmd. - * - * Do this by creating new page directory, and marking all the pages as R/W - * Then set it as the new Page Middle Directory. - * And, of course, flush the TLB so it takes effect. - * - * We save the address of the old one, for later restoration. - */ -static void acpi_create_identity_pmd (void) -{ - pgd_t *pgd; - int i; - - ptep = (pte_t*)__get_free_page(GFP_KERNEL); - - /* fill page with low mapping */ - for (i = 0; i < PTRS_PER_PTE; i++) - set_pte(ptep + i, mk_pte_phys(i << PAGE_SHIFT, PAGE_SHARED)); - - pgd = pgd_offset(current->active_mm, 0); - pmd = pmd_alloc(current->mm,pgd, 0); - - /* save the old pmd */ - saved_pmd = *pmd; - - /* set the new one */ - set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(ptep))); - - /* flush the TLB */ - local_flush_tlb(); -} - -/* - * acpi_restore_pmd - * - * Restore the old pmd saved by acpi_create_identity_pmd and - * free the page that said function alloc'd - */ -static void acpi_restore_pmd (void) -{ - set_pmd(pmd, saved_pmd); - local_flush_tlb(); - free_page((unsigned long)ptep); -} - -/** - * acpi_save_state_mem - save kernel state - * - * Create an identity mapped page table and copy the wakeup routine to - * low memory. - */ -int acpi_save_state_mem (void) -{ - acpi_create_identity_pmd(); - acpi_copy_wakeup_routine(acpi_wakeup_address); - - return 0; -} - -/** - * acpi_save_state_disk - save kernel state to disk - * - */ -int acpi_save_state_disk (void) -{ - return 1; -} - -/* - * acpi_restore_state - */ -void acpi_restore_state_mem (void) -{ - acpi_restore_pmd(); -} - -/** - * acpi_reserve_bootmem - do _very_ early ACPI initialisation - * - * We allocate a page in low memory for the wakeup - * routine for when we come back from a sleep state. The - * runtime allocator allows specification of <16M pages, but not - * <1M pages. - */ -void __init acpi_reserve_bootmem(void) -{ - acpi_wakeup_address = (unsigned long)alloc_bootmem_low(PAGE_SIZE); - if (!acpi_wakeup_address) - printk(KERN_ERR "ACPI: Cannot allocate lowmem, S3 disabled.\n"); -} - -void do_suspend_lowlevel_s4bios(int resume) -{ - if (!resume) { - save_processor_context(); - acpi_save_register_state((unsigned long)&&acpi_sleep_done); - acpi_enter_sleep_state_s4bios(); - return; - } -acpi_sleep_done: - restore_processor_context(); -} - - -#endif /*CONFIG_ACPI_SLEEP*/ - diff --git a/xen/arch/x86/acpi/boot.c b/xen/arch/x86/acpi/boot.c new file mode 100644 index 0000000000..971b3d352c --- /dev/null +++ b/xen/arch/x86/acpi/boot.c @@ -0,0 +1,912 @@ +/* + * boot.c - Architecture-Specific Low-Level ACPI Boot Support + * + * Copyright (C) 2001, 2002 Paul Diefenbaugh + * Copyright (C) 2001 Jun Nakajima + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int sbf_port; /* XXX XEN */ + +#ifdef CONFIG_X86_64 + +static inline void acpi_madt_oem_check(char *oem_id, char *oem_table_id) { } +extern void __init clustered_apic_check(void); +static inline int ioapic_setup_disabled(void) { return 0; } +#include + +#else /* X86 */ + +#ifdef CONFIG_X86_LOCAL_APIC +#include +#include +#endif /* CONFIG_X86_LOCAL_APIC */ + +#endif /* X86 */ + +#define BAD_MADT_ENTRY(entry, end) ( \ + (!entry) || (unsigned long)entry + sizeof(*entry) > end || \ + ((acpi_table_entry_header *)entry)->length != sizeof(*entry)) + +#define PREFIX "ACPI: " + +#ifdef CONFIG_ACPI_PCI +int acpi_noirq __initdata; /* skip ACPI IRQ initialization */ +int acpi_pci_disabled __initdata; /* skip ACPI PCI scan and IRQ initialization */ +#else +int acpi_noirq __initdata = 1; +int acpi_pci_disabled __initdata = 1; +#endif +int acpi_ht __initdata = 1; /* enable HT */ + +int acpi_lapic; +int acpi_ioapic; +int acpi_strict; +EXPORT_SYMBOL(acpi_strict); + +acpi_interrupt_flags acpi_sci_flags __initdata; +int acpi_sci_override_gsi __initdata; +int acpi_skip_timer_override __initdata; + +#ifdef CONFIG_X86_LOCAL_APIC +static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE; +#endif + +#ifndef __HAVE_ARCH_CMPXCHG +#warning ACPI uses CMPXCHG, i486 and later hardware +#endif + +#define MAX_MADT_ENTRIES 256 +u8 x86_acpiid_to_apicid[MAX_MADT_ENTRIES] = + { [0 ... MAX_MADT_ENTRIES-1] = 0xff }; +EXPORT_SYMBOL(x86_acpiid_to_apicid); + +/* -------------------------------------------------------------------------- + Boot-time Configuration + -------------------------------------------------------------------------- */ + +/* + * The default interrupt routing model is PIC (8259). This gets + * overriden if IOAPICs are enumerated (below). + */ +enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_PIC; + +#ifdef CONFIG_X86_64 + +/* rely on all ACPI tables being in the direct mapping */ +char *__acpi_map_table(unsigned long phys_addr, unsigned long size) +{ + if (!phys_addr || !size) + return NULL; + + if (phys_addr < (end_pfn_map << PAGE_SHIFT)) + return __va(phys_addr); + + return NULL; +} + +#else + +/* + * Temporarily use the virtual area starting from FIX_IO_APIC_BASE_END, + * to map the target physical address. The problem is that set_fixmap() + * provides a single page, and it is possible that the page is not + * sufficient. + * By using this area, we can map up to MAX_IO_APICS pages temporarily, + * i.e. until the next __va_range() call. + * + * Important Safety Note: The fixed I/O APIC page numbers are *subtracted* + * from the fixed base. That's why we start at FIX_IO_APIC_BASE_END and + * count idx down while incrementing the phys address. + */ +char *__acpi_map_table(unsigned long phys, unsigned long size) +{ + unsigned long base, offset, mapped_size; + int idx; + + if (phys + size < 8*1024*1024) + return __va(phys); + + offset = phys & (PAGE_SIZE - 1); + mapped_size = PAGE_SIZE - offset; + set_fixmap(FIX_ACPI_END, phys); + base = fix_to_virt(FIX_ACPI_END); + + /* + * Most cases can be covered by the below. + */ + idx = FIX_ACPI_END; + while (mapped_size < size) { + if (--idx < FIX_ACPI_BEGIN) + return NULL; /* cannot handle this */ + phys += PAGE_SIZE; + set_fixmap(idx, phys); + mapped_size += PAGE_SIZE; + } + + return ((unsigned char *) base + offset); +} +#endif + +#ifdef CONFIG_PCI_MMCONFIG +static int __init acpi_parse_mcfg(unsigned long phys_addr, unsigned long size) +{ + struct acpi_table_mcfg *mcfg; + + if (!phys_addr || !size) + return -EINVAL; + + mcfg = (struct acpi_table_mcfg *) __acpi_map_table(phys_addr, size); + if (!mcfg) { + printk(KERN_WARNING PREFIX "Unable to map MCFG\n"); + return -ENODEV; + } + + if (mcfg->base_reserved) { + printk(KERN_ERR PREFIX "MMCONFIG not in low 4GB of memory\n"); + return -ENODEV; + } + + pci_mmcfg_base_addr = mcfg->base_address; + + return 0; +} +#else +#define acpi_parse_mcfg NULL +#endif /* !CONFIG_PCI_MMCONFIG */ + +#ifdef CONFIG_X86_LOCAL_APIC +static int __init +acpi_parse_madt ( + unsigned long phys_addr, + unsigned long size) +{ + struct acpi_table_madt *madt = NULL; + + if (!phys_addr || !size) + return -EINVAL; + + madt = (struct acpi_table_madt *) __acpi_map_table(phys_addr, size); + if (!madt) { + printk(KERN_WARNING PREFIX "Unable to map MADT\n"); + return -ENODEV; + } + + if (madt->lapic_address) { + acpi_lapic_addr = (u64) madt->lapic_address; + + printk(KERN_DEBUG PREFIX "Local APIC address 0x%08x\n", + madt->lapic_address); + } + + acpi_madt_oem_check(madt->header.oem_id, madt->header.oem_table_id); + + return 0; +} + + +static int __init +acpi_parse_lapic ( + acpi_table_entry_header *header, const unsigned long end) +{ + struct acpi_table_lapic *processor = NULL; + + processor = (struct acpi_table_lapic*) header; + + if (BAD_MADT_ENTRY(processor, end)) + return -EINVAL; + + acpi_table_print_madt_entry(header); + + /* no utility in registering a disabled processor */ + if (processor->flags.enabled == 0) + return 0; + + x86_acpiid_to_apicid[processor->acpi_id] = processor->id; + + mp_register_lapic ( + processor->id, /* APIC ID */ + processor->flags.enabled); /* Enabled? */ + + return 0; +} + +static int __init +acpi_parse_lapic_addr_ovr ( + acpi_table_entry_header *header, const unsigned long end) +{ + struct acpi_table_lapic_addr_ovr *lapic_addr_ovr = NULL; + + lapic_addr_ovr = (struct acpi_table_lapic_addr_ovr*) header; + + if (BAD_MADT_ENTRY(lapic_addr_ovr, end)) + return -EINVAL; + + acpi_lapic_addr = lapic_addr_ovr->address; + + return 0; +} + +static int __init +acpi_parse_lapic_nmi ( + acpi_table_entry_header *header, const unsigned long end) +{ + struct acpi_table_lapic_nmi *lapic_nmi = NULL; + + lapic_nmi = (struct acpi_table_lapic_nmi*) header; + + if (BAD_MADT_ENTRY(lapic_nmi, end)) + return -EINVAL; + + acpi_table_print_madt_entry(header); + + if (lapic_nmi->lint != 1) + printk(KERN_WARNING PREFIX "NMI not connected to LINT 1!\n"); + + return 0; +} + + +#endif /*CONFIG_X86_LOCAL_APIC*/ + +#if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_ACPI_INTERPRETER) + +static int __init +acpi_parse_ioapic ( + acpi_table_entry_header *header, const unsigned long end) +{ + struct acpi_table_ioapic *ioapic = NULL; + + ioapic = (struct acpi_table_ioapic*) header; + + if (BAD_MADT_ENTRY(ioapic, end)) + return -EINVAL; + + acpi_table_print_madt_entry(header); + + mp_register_ioapic ( + ioapic->id, + ioapic->address, + ioapic->global_irq_base); + + return 0; +} + +/* + * Parse Interrupt Source Override for the ACPI SCI + */ +static void +acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger) +{ + if (trigger == 0) /* compatible SCI trigger is level */ + trigger = 3; + + if (polarity == 0) /* compatible SCI polarity is low */ + polarity = 3; + + /* Command-line over-ride via acpi_sci= */ + if (acpi_sci_flags.trigger) + trigger = acpi_sci_flags.trigger; + + if (acpi_sci_flags.polarity) + polarity = acpi_sci_flags.polarity; + + /* + * mp_config_acpi_legacy_irqs() already setup IRQs < 16 + * If GSI is < 16, this will update its flags, + * else it will create a new mp_irqs[] entry. + */ + mp_override_legacy_irq(gsi, polarity, trigger, gsi); + + /* + * stash over-ride to indicate we've been here + * and for later update of acpi_fadt + */ + acpi_sci_override_gsi = gsi; + return; +} + +static int __init +acpi_parse_int_src_ovr ( + acpi_table_entry_header *header, const unsigned long end) +{ + struct acpi_table_int_src_ovr *intsrc = NULL; + + intsrc = (struct acpi_table_int_src_ovr*) header; + + if (BAD_MADT_ENTRY(intsrc, end)) + return -EINVAL; + + acpi_table_print_madt_entry(header); + + if (intsrc->bus_irq == acpi_fadt.sci_int) { + acpi_sci_ioapic_setup(intsrc->global_irq, + intsrc->flags.polarity, intsrc->flags.trigger); + return 0; + } + + if (acpi_skip_timer_override && + intsrc->bus_irq == 0 && intsrc->global_irq == 2) { + printk(PREFIX "BIOS IRQ0 pin2 override ignored.\n"); + return 0; + } + + mp_override_legacy_irq ( + intsrc->bus_irq, + intsrc->flags.polarity, + intsrc->flags.trigger, + intsrc->global_irq); + + return 0; +} + + +static int __init +acpi_parse_nmi_src ( + acpi_table_entry_header *header, const unsigned long end) +{ + struct acpi_table_nmi_src *nmi_src = NULL; + + nmi_src = (struct acpi_table_nmi_src*) header; + + if (BAD_MADT_ENTRY(nmi_src, end)) + return -EINVAL; + + acpi_table_print_madt_entry(header); + + /* TBD: Support nimsrc entries? */ + + return 0; +} + +#endif /* CONFIG_X86_IO_APIC */ + +#ifdef CONFIG_ACPI_BUS + +/* + * acpi_pic_sci_set_trigger() + * + * use ELCR to set PIC-mode trigger type for SCI + * + * If a PIC-mode SCI is not recognized or gives spurious IRQ7's + * it may require Edge Trigger -- use "acpi_sci=edge" + * + * Port 0x4d0-4d1 are ECLR1 and ECLR2, the Edge/Level Control Registers + * for the 8259 PIC. bit[n] = 1 means irq[n] is Level, otherwise Edge. + * ECLR1 is IRQ's 0-7 (IRQ 0, 1, 2 must be 0) + * ECLR2 is IRQ's 8-15 (IRQ 8, 13 must be 0) + */ + +void __init +acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger) +{ + unsigned int mask = 1 << irq; + unsigned int old, new; + + /* Real old ELCR mask */ + old = inb(0x4d0) | (inb(0x4d1) << 8); + + /* + * If we use ACPI to set PCI irq's, then we should clear ELCR + * since we will set it correctly as we enable the PCI irq + * routing. + */ + new = acpi_noirq ? old : 0; + + /* + * Update SCI information in the ELCR, it isn't in the PCI + * routing tables.. + */ + switch (trigger) { + case 1: /* Edge - clear */ + new &= ~mask; + break; + case 3: /* Level - set */ + new |= mask; + break; + } + + if (old == new) + return; + + printk(PREFIX "setting ELCR to %04x (from %04x)\n", new, old); + outb(new, 0x4d0); + outb(new >> 8, 0x4d1); +} + + +#endif /* CONFIG_ACPI_BUS */ + +int acpi_gsi_to_irq(u32 gsi, unsigned int *irq) +{ +#ifdef CONFIG_X86_IO_APIC + if (use_pci_vector() && !platform_legacy_irq(gsi)) + *irq = IO_APIC_VECTOR(gsi); + else +#endif + *irq = gsi; + return 0; +} + +unsigned int acpi_register_gsi(u32 gsi, int edge_level, int active_high_low) +{ + unsigned int irq; + unsigned int plat_gsi = gsi; + +#ifdef CONFIG_PCI + /* + * Make sure all (legacy) PCI IRQs are set as level-triggered. + */ + if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) { + extern void eisa_set_level_irq(unsigned int irq); + + if (edge_level == ACPI_LEVEL_SENSITIVE) + eisa_set_level_irq(gsi); + } +#endif + +#ifdef CONFIG_X86_IO_APIC + if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) { + plat_gsi = mp_register_gsi(gsi, edge_level, active_high_low); + } +#endif + acpi_gsi_to_irq(plat_gsi, &irq); + return irq; +} +EXPORT_SYMBOL(acpi_register_gsi); + +/* + * ACPI based hotplug support for CPU + */ +#ifdef CONFIG_ACPI_HOTPLUG_CPU +int +acpi_map_lsapic(acpi_handle handle, int *pcpu) +{ + /* TBD */ + return -EINVAL; +} +EXPORT_SYMBOL(acpi_map_lsapic); + + +int +acpi_unmap_lsapic(int cpu) +{ + /* TBD */ + return -EINVAL; +} +EXPORT_SYMBOL(acpi_unmap_lsapic); +#endif /* CONFIG_ACPI_HOTPLUG_CPU */ + +static unsigned long __init +acpi_scan_rsdp ( + unsigned long start, + unsigned long length) +{ + unsigned long offset = 0; + unsigned long sig_len = sizeof("RSD PTR ") - 1; + + /* + * Scan all 16-byte boundaries of the physical memory region for the + * RSDP signature. + */ + for (offset = 0; offset < length; offset += 16) { + if (strncmp((char *) (start + offset), "RSD PTR ", sig_len)) + continue; + return (start + offset); + } + + return 0; +} + +static int __init acpi_parse_sbf(unsigned long phys_addr, unsigned long size) +{ + struct acpi_table_sbf *sb; + + if (!phys_addr || !size) + return -EINVAL; + + sb = (struct acpi_table_sbf *) __acpi_map_table(phys_addr, size); + if (!sb) { + printk(KERN_WARNING PREFIX "Unable to map SBF\n"); + return -ENODEV; + } + + sbf_port = sb->sbf_cmos; /* Save CMOS port */ + + return 0; +} + + +#ifdef CONFIG_HPET_TIMER + +static int __init acpi_parse_hpet(unsigned long phys, unsigned long size) +{ + struct acpi_table_hpet *hpet_tbl; + + if (!phys || !size) + return -EINVAL; + + hpet_tbl = (struct acpi_table_hpet *) __acpi_map_table(phys, size); + if (!hpet_tbl) { + printk(KERN_WARNING PREFIX "Unable to map HPET\n"); + return -ENODEV; + } + + if (hpet_tbl->addr.space_id != ACPI_SPACE_MEM) { + printk(KERN_WARNING PREFIX "HPET timers must be located in " + "memory.\n"); + return -1; + } + +#ifdef CONFIG_X86_64 + vxtime.hpet_address = hpet_tbl->addr.addrl | + ((long) hpet_tbl->addr.addrh << 32); + + printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n", + hpet_tbl->id, vxtime.hpet_address); +#else /* X86 */ + { + extern unsigned long hpet_address; + + hpet_address = hpet_tbl->addr.addrl; + printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n", + hpet_tbl->id, hpet_address); + } +#endif /* X86 */ + + return 0; +} +#else +#define acpi_parse_hpet NULL +#endif + +#ifdef CONFIG_X86_PM_TIMER +extern u32 pmtmr_ioport; +#endif + +static int __init acpi_parse_fadt(unsigned long phys, unsigned long size) +{ + struct fadt_descriptor_rev2 *fadt = NULL; + + fadt = (struct fadt_descriptor_rev2*) __acpi_map_table(phys,size); + if(!fadt) { + printk(KERN_WARNING PREFIX "Unable to map FADT\n"); + return 0; + } + +#ifdef CONFIG_ACPI_INTERPRETER + /* initialize sci_int early for INT_SRC_OVR MADT parsing */ + acpi_fadt.sci_int = fadt->sci_int; +#endif + +#ifdef CONFIG_X86_PM_TIMER + /* detect the location of the ACPI PM Timer */ + if (fadt->revision >= FADT2_REVISION_ID) { + /* FADT rev. 2 */ + if (fadt->xpm_tmr_blk.address_space_id != ACPI_ADR_SPACE_SYSTEM_IO) + return 0; + + pmtmr_ioport = fadt->xpm_tmr_blk.address; + } else { + /* FADT rev. 1 */ + pmtmr_ioport = fadt->V1_pm_tmr_blk; + } + if (pmtmr_ioport) + printk(KERN_INFO PREFIX "PM-Timer IO Port: %#x\n", pmtmr_ioport); +#endif + return 0; +} + + +unsigned long __init +acpi_find_rsdp (void) +{ + unsigned long rsdp_phys = 0; + +#if 0 + if (efi_enabled) { + if (efi.acpi20) + return __pa(efi.acpi20); + else if (efi.acpi) + return __pa(efi.acpi); + } +#endif + /* + * Scan memory looking for the RSDP signature. First search EBDA (low + * memory) paragraphs and then search upper memory (E0000-FFFFF). + */ + rsdp_phys = acpi_scan_rsdp (0, 0x400); + if (!rsdp_phys) + rsdp_phys = acpi_scan_rsdp (0xE0000, 0xFFFFF); + + return rsdp_phys; +} + +#ifdef CONFIG_X86_LOCAL_APIC +/* + * Parse LAPIC entries in MADT + * returns 0 on success, < 0 on error + */ +static int __init +acpi_parse_madt_lapic_entries(void) +{ + int count; + + /* + * Note that the LAPIC address is obtained from the MADT (32-bit value) + * and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value). + */ + + count = acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR, acpi_parse_lapic_addr_ovr, 0); + if (count < 0) { + printk(KERN_ERR PREFIX "Error parsing LAPIC address override entry\n"); + return count; + } + + mp_register_lapic_address(acpi_lapic_addr); + + count = acpi_table_parse_madt(ACPI_MADT_LAPIC, acpi_parse_lapic, + MAX_APICS); + if (!count) { + printk(KERN_ERR PREFIX "No LAPIC entries present\n"); + /* TBD: Cleanup to allow fallback to MPS */ + return -ENODEV; + } + else if (count < 0) { + printk(KERN_ERR PREFIX "Error parsing LAPIC entry\n"); + /* TBD: Cleanup to allow fallback to MPS */ + return count; + } + + count = acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi, 0); + if (count < 0) { + printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n"); + /* TBD: Cleanup to allow fallback to MPS */ + return count; + } + return 0; +} +#endif /* CONFIG_X86_LOCAL_APIC */ + +#if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_ACPI_INTERPRETER) +/* + * Parse IOAPIC related entries in MADT + * returns 0 on success, < 0 on error + */ +static int __init +acpi_parse_madt_ioapic_entries(void) +{ + int count; + + /* + * ACPI interpreter is required to complete interrupt setup, + * so if it is off, don't enumerate the io-apics with ACPI. + * If MPS is present, it will handle them, + * otherwise the system will stay in PIC mode + */ + if (acpi_disabled || acpi_noirq) { + return -ENODEV; + } + + /* + * if "noapic" boot option, don't look for IO-APICs + */ + if (skip_ioapic_setup) { + printk(KERN_INFO PREFIX "Skipping IOAPIC probe " + "due to 'noapic' option.\n"); + return -ENODEV; + } + + count = acpi_table_parse_madt(ACPI_MADT_IOAPIC, acpi_parse_ioapic, MAX_IO_APICS); + if (!count) { + printk(KERN_ERR PREFIX "No IOAPIC entries present\n"); + return -ENODEV; + } + else if (count < 0) { + printk(KERN_ERR PREFIX "Error parsing IOAPIC entry\n"); + return count; + } + + count = acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr, NR_IRQ_VECTORS); + if (count < 0) { + printk(KERN_ERR PREFIX "Error parsing interrupt source overrides entry\n"); + /* TBD: Cleanup to allow fallback to MPS */ + return count; + } + + /* + * If BIOS did not supply an INT_SRC_OVR for the SCI + * pretend we got one so we can set the SCI flags. + */ + if (!acpi_sci_override_gsi) + acpi_sci_ioapic_setup(acpi_fadt.sci_int, 0, 0); + + /* Fill in identity legacy mapings where no override */ + mp_config_acpi_legacy_irqs(); + + count = acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src, NR_IRQ_VECTORS); + if (count < 0) { + printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n"); + /* TBD: Cleanup to allow fallback to MPS */ + return count; + } + + return 0; +} +#else +static inline int acpi_parse_madt_ioapic_entries(void) +{ + return -1; +} +#endif /* !(CONFIG_X86_IO_APIC && CONFIG_ACPI_INTERPRETER) */ + + +static void __init +acpi_process_madt(void) +{ +#ifdef CONFIG_X86_LOCAL_APIC + int count, error; + + count = acpi_table_parse(ACPI_APIC, acpi_parse_madt); + if (count >= 1) { + + /* + * Parse MADT LAPIC entries + */ + error = acpi_parse_madt_lapic_entries(); + if (!error) { + acpi_lapic = 1; + + /* + * Parse MADT IO-APIC entries + */ + error = acpi_parse_madt_ioapic_entries(); + if (!error) { + acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC; + acpi_irq_balance_set(NULL); + acpi_ioapic = 1; + + smp_found_config = 1; + clustered_apic_check(); + } + } + if (error == -EINVAL) { + /* + * Dell Precision Workstation 410, 610 come here. + */ + printk(KERN_ERR PREFIX "Invalid BIOS MADT, disabling ACPI\n"); + disable_acpi(); + } + } +#endif + return; +} + +/* + * acpi_boot_table_init() and acpi_boot_init() + * called from setup_arch(), always. + * 1. checksums all tables + * 2. enumerates lapics + * 3. enumerates io-apics + * + * acpi_table_init() is separate to allow reading SRAT without + * other side effects. + * + * side effects of acpi_boot_init: + * acpi_lapic = 1 if LAPIC found + * acpi_ioapic = 1 if IOAPIC found + * if (acpi_lapic && acpi_ioapic) smp_found_config = 1; + * if acpi_blacklisted() acpi_disabled = 1; + * acpi_irq_model=... + * ... + * + * return value: (currently ignored) + * 0: success + * !0: failure + */ + +int __init +acpi_boot_table_init(void) +{ + int error; + + /* + * If acpi_disabled, bail out + * One exception: acpi=ht continues far enough to enumerate LAPICs + */ + if (acpi_disabled && !acpi_ht) + return 1; + + /* + * Initialize the ACPI boot-time table parser. + */ + error = acpi_table_init(); + if (error) { + disable_acpi(); + return error; + } + +#if 0 /*def __i386__*/ + check_acpi_pci(); +#endif + + acpi_table_parse(ACPI_BOOT, acpi_parse_sbf); + + /* + * blacklist may disable ACPI entirely + */ + error = acpi_blacklisted(); + if (error) { + extern int acpi_force; + + if (acpi_force) { + printk(KERN_WARNING PREFIX "acpi=force override\n"); + } else { + printk(KERN_WARNING PREFIX "Disabling ACPI support\n"); + disable_acpi(); + return error; + } + } + + return 0; +} + + +int __init acpi_boot_init(void) +{ + /* + * If acpi_disabled, bail out + * One exception: acpi=ht continues far enough to enumerate LAPICs + */ + if (acpi_disabled && !acpi_ht) + return 1; + + acpi_table_parse(ACPI_BOOT, acpi_parse_sbf); + + /* + * set sci_int and PM timer address + */ + acpi_table_parse(ACPI_FADT, acpi_parse_fadt); + + /* + * Process the Multiple APIC Description Table (MADT), if present + */ + acpi_process_madt(); + + acpi_table_parse(ACPI_HPET, acpi_parse_hpet); + acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg); + + return 0; +} + diff --git a/xen/arch/x86/apic.c b/xen/arch/x86/apic.c index 766a10ed7c..f368608635 100644 --- a/xen/arch/x86/apic.c +++ b/xen/arch/x86/apic.c @@ -34,14 +34,27 @@ #include #include #include -#include -#include +#include +#include /* Using APIC to generate smp_local_timer_interrupt? */ int using_apic_timer = 0; +int apic_verbosity; + static int enabled_via_apicbase; +int get_physical_broadcast(void) +{ + unsigned int lvr, version; + lvr = apic_read(APIC_LVR); + version = GET_APIC_VERSION(lvr); + if (!APIC_INTEGRATED(version) || version >= 0x14) + return 0xff; + else + return 0xf; +} + int get_maxlvt(void) { unsigned int v, ver, maxlvt; @@ -907,7 +920,7 @@ int __init APIC_init_uniprocessor (void) #ifdef CONFIG_SMP cpu_online_map = 1; #endif - phys_cpu_present_map = 1; + phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid); apic_write_around(APIC_ID, boot_cpu_physical_apicid); setup_local_APIC(); diff --git a/xen/arch/x86/i8259.c b/xen/arch/x86/i8259.c index 62eb07ada0..8111260050 100644 --- a/xen/arch/x86/i8259.c +++ b/xen/arch/x86/i8259.c @@ -45,7 +45,7 @@ BUILD_COMMON_IRQ() /* * ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts: - * (these are usually mapped to vectors 0x30-0x3f) + * (these are usually mapped to vectors 0x20-0x2f) */ BUILD_16_IRQS(0x0) @@ -58,7 +58,7 @@ BUILD_16_IRQS(0x0) * of these. Plus, more powerful systems might have more than 64 * IO-APIC registers. * - * (these are usually mapped into the 0x30-0xff vector range) + * (these are usually mapped into the 0x20-0xff vector range) */ BUILD_16_IRQS(0x1) BUILD_16_IRQS(0x2) BUILD_16_IRQS(0x3) BUILD_16_IRQS(0x4) BUILD_16_IRQS(0x5) BUILD_16_IRQS(0x6) BUILD_16_IRQS(0x7) @@ -101,7 +101,7 @@ BUILD_SMP_INTERRUPT(spurious_interrupt,SPURIOUS_APIC_VECTOR) IRQ(x,8), IRQ(x,9), IRQ(x,a), IRQ(x,b), \ IRQ(x,c), IRQ(x,d), IRQ(x,e), IRQ(x,f) - void *interrupt[NR_IRQS] = { + void (*interrupt[NR_IRQS])(void) = { IRQLIST_16(0x0), #ifdef CONFIG_X86_IO_APIC @@ -341,7 +341,7 @@ void __init init_8259A(int auto_eoi) * outb_p - this has to work on a wide range of PC hardware. */ outb_p(0x11, 0x20); /* ICW1: select 8259A-1 init */ - outb_p(0x30 + 0, 0x21); /* ICW2: 8259A-1 IR0-7 mapped to 0x30-0x37 */ + outb_p(0x20 + 0, 0x21); /* ICW2: 8259A-1 IR0-7 mapped to 0x20-0x27 */ outb_p(0x04, 0x21); /* 8259A-1 (the master) has a slave on IR2 */ if (auto_eoi) outb_p(0x03, 0x21); /* master does Auto EOI */ @@ -349,7 +349,7 @@ void __init init_8259A(int auto_eoi) outb_p(0x01, 0x21); /* master expects normal EOI */ outb_p(0x11, 0xA0); /* ICW1: select 8259A-2 init */ - outb_p(0x30 + 8, 0xA1); /* ICW2: 8259A-2 IR0-7 mapped to 0x38-0x3f */ + outb_p(0x20 + 8, 0xA1); /* ICW2: 8259A-2 IR0-7 mapped to 0x28-0x2f */ outb_p(0x02, 0xA1); /* 8259A-2 is a slave on master's IR2 */ outb_p(0x01, 0xA1); /* (slave's support for AEOI in flat mode is to be investigated) */ diff --git a/xen/arch/x86/io_apic.c b/xen/arch/x86/io_apic.c index 5ed95ff5f8..929117c95c 100644 --- a/xen/arch/x86/io_apic.c +++ b/xen/arch/x86/io_apic.c @@ -25,26 +25,20 @@ #include #include #include -#include -#include +#include #include -#include -#include +#include #include #include -#include - -#ifdef CONFIG_X86_IO_APIC +#include +#include -#undef APIC_LOCKUP_DEBUG +int (*ioapic_renumber_irq)(int ioapic, int irq); +atomic_t irq_mis_count; -#define APIC_LOCKUP_DEBUG - -static spinlock_t ioapic_lock = SPIN_LOCK_UNLOCKED; - -unsigned int int_dest_addr_mode = APIC_DEST_LOGICAL; -unsigned char int_delivery_mode = dest_LowestPrio; +static DEFINE_SPINLOCK(ioapic_lock); +int skip_ioapic_setup; /* * # of IRQ routing registers @@ -69,12 +63,20 @@ static struct irq_pin_list { int apic, pin, next; } irq_2_pin[PIN_MAP_SIZE]; +int vector_irq[NR_VECTORS] = { [0 ... NR_VECTORS - 1] = -1}; +#ifdef CONFIG_PCI_MSI +#define vector_to_irq(vector) \ + (platform_legacy_irq(vector) ? vector : vector_irq[vector]) +#else +#define vector_to_irq(vector) (vector) +#endif + /* * The common case is 1:1 IRQ<->pin mappings. Sometimes there are * shared ISA-space IRQs, so we have to support them. We are super * fast in the common case, and fast for shared ISA-space IRQs. */ -static void __init add_pin_to_irq(unsigned int irq, int apic, int pin) +static void add_pin_to_irq(unsigned int irq, int apic, int pin) { static int first_free_entry = NR_IRQS; struct irq_pin_list *entry = irq_2_pin + irq; @@ -112,36 +114,48 @@ static void __init replace_pin_at_irq(unsigned int irq, } } -#define __DO_ACTION(R, ACTION, FINAL) \ - \ -{ \ - int pin; \ - struct irq_pin_list *entry = irq_2_pin + irq; \ - \ - for (;;) { \ - unsigned int reg; \ - pin = entry->pin; \ - if (pin == -1) \ - break; \ - reg = io_apic_read(entry->apic, 0x10 + R + pin*2); \ - reg ACTION; \ - io_apic_write(entry->apic, 0x10 + R + pin*2, reg); \ - if (!entry->next) \ - break; \ - entry = irq_2_pin + entry->next; \ - } \ - FINAL; \ -} - -#define DO_ACTION(name,R,ACTION, FINAL) \ - \ - static void name##_IO_APIC_irq (unsigned int irq) \ - __DO_ACTION(R, ACTION, FINAL) - -DO_ACTION( __mask, 0, |= 0x00010000, io_apic_sync(entry->apic) ) -DO_ACTION( __unmask, 0, &= 0xfffeffff, ) -DO_ACTION( __edge, 0, &= 0xffff7fff, ) -DO_ACTION( __level, 0, |= 0x00008000, ) +static void __modify_IO_APIC_irq (unsigned int irq, unsigned long enable, unsigned long disable) +{ + struct irq_pin_list *entry = irq_2_pin + irq; + unsigned int pin, reg; + + for (;;) { + pin = entry->pin; + if (pin == -1) + break; + reg = io_apic_read(entry->apic, 0x10 + pin*2); + reg &= ~disable; + reg |= enable; + io_apic_modify(entry->apic, 0x10 + pin*2, reg); + if (!entry->next) + break; + entry = irq_2_pin + entry->next; + } +} + +/* mask = 1 */ +static void __mask_IO_APIC_irq (unsigned int irq) +{ + __modify_IO_APIC_irq(irq, 0x00010000, 0); +} + +/* mask = 0 */ +static void __unmask_IO_APIC_irq (unsigned int irq) +{ + __modify_IO_APIC_irq(irq, 0, 0x00010000); +} + +/* mask = 1, trigger = 0 */ +static void __mask_and_edge_IO_APIC_irq (unsigned int irq) +{ + __modify_IO_APIC_irq(irq, 0x00010000, 0x00008000); +} + +/* mask = 0, trigger = 1 */ +static void __unmask_and_level_IO_APIC_irq (unsigned int irq) +{ + __modify_IO_APIC_irq(irq, 0x00008000, 0x00010000); +} static void mask_IO_APIC_irq (unsigned int irq) { @@ -165,7 +179,7 @@ void clear_IO_APIC_pin(unsigned int apic, unsigned int pin) { struct IO_APIC_route_entry entry; unsigned long flags; - + /* Check delivery_mode to be sure we're not clearing an SMI pin */ spin_lock_irqsave(&ioapic_lock, flags); *(((int*)&entry) + 0) = io_apic_read(apic, 0x10 + 2 * pin); @@ -194,85 +208,467 @@ static void clear_IO_APIC (void) clear_IO_APIC_pin(apic, pin); } -static void set_ioapic_affinity (unsigned int irq, unsigned long mask) +static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t cpumask) { unsigned long flags; - - /* - * Only the first 8 bits are valid. - */ - mask = mask << 24; + int pin; + struct irq_pin_list *entry = irq_2_pin + irq; + unsigned int apicid_value; + + apicid_value = cpu_mask_to_apicid(cpumask); + /* Prepare to do the io_apic_write */ + apicid_value = apicid_value << 24; spin_lock_irqsave(&ioapic_lock, flags); - __DO_ACTION(1, = mask, ) + for (;;) { + pin = entry->pin; + if (pin == -1) + break; + io_apic_write(entry->apic, 0x10 + 1 + pin*2, apicid_value); + if (!entry->next) + break; + entry = irq_2_pin + entry->next; + } spin_unlock_irqrestore(&ioapic_lock, flags); } -#define balance_irq(_irq) ((void)0) +#if defined(CONFIG_IRQBALANCE) +# include /* kernel_thread() */ +# include /* kstat */ +# include /* kmalloc() */ +# include /* time_after() */ + +# ifdef CONFIG_BALANCED_IRQ_DEBUG +# define TDprintk(x...) do { printk("<%ld:%s:%d>: ", jiffies, __FILE__, __LINE__); printk(x); } while (0) +# define Dprintk(x...) do { TDprintk(x); } while (0) +# else +# define TDprintk(x...) +# define Dprintk(x...) +# endif -/* - * support for broken MP BIOSs, enables hand-redirection of PIRQ0-7 to - * specific CPU-side IRQs. - */ +cpumask_t __cacheline_aligned pending_irq_balance_cpumask[NR_IRQS]; -#define MAX_PIRQS 8 -int pirq_entries [MAX_PIRQS]; -int pirqs_enabled; +#define IRQBALANCE_CHECK_ARCH -999 +static int irqbalance_disabled = IRQBALANCE_CHECK_ARCH; +static int physical_balance = 0; -int skip_ioapic_setup; -#if 0 +struct irq_cpu_info { + unsigned long * last_irq; + unsigned long * irq_delta; + unsigned long irq; +} irq_cpu_data[NR_CPUS]; + +#define CPU_IRQ(cpu) (irq_cpu_data[cpu].irq) +#define LAST_CPU_IRQ(cpu,irq) (irq_cpu_data[cpu].last_irq[irq]) +#define IRQ_DELTA(cpu,irq) (irq_cpu_data[cpu].irq_delta[irq]) -static int __init noioapic_setup(char *str) +#define IDLE_ENOUGH(cpu,now) \ + (idle_cpu(cpu) && ((now) - irq_stat[(cpu)].idle_timestamp > 1)) + +#define IRQ_ALLOWED(cpu, allowed_mask) cpu_isset(cpu, allowed_mask) + +#define CPU_TO_PACKAGEINDEX(i) (first_cpu(cpu_sibling_map[i])) + +#define MAX_BALANCED_IRQ_INTERVAL (5*HZ) +#define MIN_BALANCED_IRQ_INTERVAL (HZ/2) +#define BALANCED_IRQ_MORE_DELTA (HZ/10) +#define BALANCED_IRQ_LESS_DELTA (HZ) + +long balanced_irq_interval = MAX_BALANCED_IRQ_INTERVAL; + +static unsigned long move(int curr_cpu, cpumask_t allowed_mask, + unsigned long now, int direction) { - skip_ioapic_setup = 1; - return 1; + int search_idle = 1; + int cpu = curr_cpu; + + goto inside; + + do { + if (unlikely(cpu == curr_cpu)) + search_idle = 0; +inside: + if (direction == 1) { + cpu++; + if (cpu >= NR_CPUS) + cpu = 0; + } else { + cpu--; + if (cpu == -1) + cpu = NR_CPUS-1; + } + } while (!cpu_online(cpu) || !IRQ_ALLOWED(cpu,allowed_mask) || + (search_idle && !IDLE_ENOUGH(cpu,now))); + + return cpu; } -__setup("noapic", noioapic_setup); +static inline void balance_irq(int cpu, int irq) +{ + unsigned long now = jiffies; + cpumask_t allowed_mask; + unsigned int new_cpu; + + if (irqbalance_disabled) + return; + + cpus_and(allowed_mask, cpu_online_map, irq_affinity[irq]); + new_cpu = move(cpu, allowed_mask, now, 1); + if (cpu != new_cpu) { + irq_desc_t *desc = irq_desc + irq; + unsigned long flags; + + spin_lock_irqsave(&desc->lock, flags); + pending_irq_balance_cpumask[irq] = cpumask_of_cpu(new_cpu); + spin_unlock_irqrestore(&desc->lock, flags); + } +} -static int __init ioapic_setup(char *str) +static inline void rotate_irqs_among_cpus(unsigned long useful_load_threshold) { - skip_ioapic_setup = 0; - return 1; + int i, j; + Dprintk("Rotating IRQs among CPUs.\n"); + for (i = 0; i < NR_CPUS; i++) { + for (j = 0; cpu_online(i) && (j < NR_IRQS); j++) { + if (!irq_desc[j].action) + continue; + /* Is it a significant load ? */ + if (IRQ_DELTA(CPU_TO_PACKAGEINDEX(i),j) < + useful_load_threshold) + continue; + balance_irq(i, j); + } + } + balanced_irq_interval = max((long)MIN_BALANCED_IRQ_INTERVAL, + balanced_irq_interval - BALANCED_IRQ_LESS_DELTA); + return; } -__setup("apic", ioapic_setup); +static void do_irq_balance(void) +{ + int i, j; + unsigned long max_cpu_irq = 0, min_cpu_irq = (~0); + unsigned long move_this_load = 0; + int max_loaded = 0, min_loaded = 0; + int load; + unsigned long useful_load_threshold = balanced_irq_interval + 10; + int selected_irq; + int tmp_loaded, first_attempt = 1; + unsigned long tmp_cpu_irq; + unsigned long imbalance = 0; + cpumask_t allowed_mask, target_cpu_mask, tmp; + + for (i = 0; i < NR_CPUS; i++) { + int package_index; + CPU_IRQ(i) = 0; + if (!cpu_online(i)) + continue; + package_index = CPU_TO_PACKAGEINDEX(i); + for (j = 0; j < NR_IRQS; j++) { + unsigned long value_now, delta; + /* Is this an active IRQ? */ + if (!irq_desc[j].action) + continue; + if ( package_index == i ) + IRQ_DELTA(package_index,j) = 0; + /* Determine the total count per processor per IRQ */ + value_now = (unsigned long) kstat_cpu(i).irqs[j]; + + /* Determine the activity per processor per IRQ */ + delta = value_now - LAST_CPU_IRQ(i,j); + + /* Update last_cpu_irq[][] for the next time */ + LAST_CPU_IRQ(i,j) = value_now; + + /* Ignore IRQs whose rate is less than the clock */ + if (delta < useful_load_threshold) + continue; + /* update the load for the processor or package total */ + IRQ_DELTA(package_index,j) += delta; + + /* Keep track of the higher numbered sibling as well */ + if (i != package_index) + CPU_IRQ(i) += delta; + /* + * We have sibling A and sibling B in the package + * + * cpu_irq[A] = load for cpu A + load for cpu B + * cpu_irq[B] = load for cpu B + */ + CPU_IRQ(package_index) += delta; + } + } + /* Find the least loaded processor package */ + for (i = 0; i < NR_CPUS; i++) { + if (!cpu_online(i)) + continue; + if (i != CPU_TO_PACKAGEINDEX(i)) + continue; + if (min_cpu_irq > CPU_IRQ(i)) { + min_cpu_irq = CPU_IRQ(i); + min_loaded = i; + } + } + max_cpu_irq = ULONG_MAX; + +tryanothercpu: + /* Look for heaviest loaded processor. + * We may come back to get the next heaviest loaded processor. + * Skip processors with trivial loads. + */ + tmp_cpu_irq = 0; + tmp_loaded = -1; + for (i = 0; i < NR_CPUS; i++) { + if (!cpu_online(i)) + continue; + if (i != CPU_TO_PACKAGEINDEX(i)) + continue; + if (max_cpu_irq <= CPU_IRQ(i)) + continue; + if (tmp_cpu_irq < CPU_IRQ(i)) { + tmp_cpu_irq = CPU_IRQ(i); + tmp_loaded = i; + } + } + + if (tmp_loaded == -1) { + /* In the case of small number of heavy interrupt sources, + * loading some of the cpus too much. We use Ingo's original + * approach to rotate them around. + */ + if (!first_attempt && imbalance >= useful_load_threshold) { + rotate_irqs_among_cpus(useful_load_threshold); + return; + } + goto not_worth_the_effort; + } + + first_attempt = 0; /* heaviest search */ + max_cpu_irq = tmp_cpu_irq; /* load */ + max_loaded = tmp_loaded; /* processor */ + imbalance = (max_cpu_irq - min_cpu_irq) / 2; + + Dprintk("max_loaded cpu = %d\n", max_loaded); + Dprintk("min_loaded cpu = %d\n", min_loaded); + Dprintk("max_cpu_irq load = %ld\n", max_cpu_irq); + Dprintk("min_cpu_irq load = %ld\n", min_cpu_irq); + Dprintk("load imbalance = %lu\n", imbalance); + + /* if imbalance is less than approx 10% of max load, then + * observe diminishing returns action. - quit + */ + if (imbalance < (max_cpu_irq >> 3)) { + Dprintk("Imbalance too trivial\n"); + goto not_worth_the_effort; + } + +tryanotherirq: + /* if we select an IRQ to move that can't go where we want, then + * see if there is another one to try. + */ + move_this_load = 0; + selected_irq = -1; + for (j = 0; j < NR_IRQS; j++) { + /* Is this an active IRQ? */ + if (!irq_desc[j].action) + continue; + if (imbalance <= IRQ_DELTA(max_loaded,j)) + continue; + /* Try to find the IRQ that is closest to the imbalance + * without going over. + */ + if (move_this_load < IRQ_DELTA(max_loaded,j)) { + move_this_load = IRQ_DELTA(max_loaded,j); + selected_irq = j; + } + } + if (selected_irq == -1) { + goto tryanothercpu; + } + + imbalance = move_this_load; + + /* For physical_balance case, we accumlated both load + * values in the one of the siblings cpu_irq[], + * to use the same code for physical and logical processors + * as much as possible. + * + * NOTE: the cpu_irq[] array holds the sum of the load for + * sibling A and sibling B in the slot for the lowest numbered + * sibling (A), _AND_ the load for sibling B in the slot for + * the higher numbered sibling. + * + * We seek the least loaded sibling by making the comparison + * (A+B)/2 vs B + */ + load = CPU_IRQ(min_loaded) >> 1; + for_each_cpu_mask(j, cpu_sibling_map[min_loaded]) { + if (load > CPU_IRQ(j)) { + /* This won't change cpu_sibling_map[min_loaded] */ + load = CPU_IRQ(j); + min_loaded = j; + } + } + + cpus_and(allowed_mask, cpu_online_map, irq_affinity[selected_irq]); + target_cpu_mask = cpumask_of_cpu(min_loaded); + cpus_and(tmp, target_cpu_mask, allowed_mask); + + if (!cpus_empty(tmp)) { + irq_desc_t *desc = irq_desc + selected_irq; + unsigned long flags; + + Dprintk("irq = %d moved to cpu = %d\n", + selected_irq, min_loaded); + /* mark for change destination */ + spin_lock_irqsave(&desc->lock, flags); + pending_irq_balance_cpumask[selected_irq] = + cpumask_of_cpu(min_loaded); + spin_unlock_irqrestore(&desc->lock, flags); + /* Since we made a change, come back sooner to + * check for more variation. + */ + balanced_irq_interval = max((long)MIN_BALANCED_IRQ_INTERVAL, + balanced_irq_interval - BALANCED_IRQ_LESS_DELTA); + return; + } + goto tryanotherirq; + +not_worth_the_effort: + /* + * if we did not find an IRQ to move, then adjust the time interval + * upward + */ + balanced_irq_interval = min((long)MAX_BALANCED_IRQ_INTERVAL, + balanced_irq_interval + BALANCED_IRQ_MORE_DELTA); + Dprintk("IRQ worth rotating not found\n"); + return; +} +static int balanced_irq(void *unused) +{ + int i; + unsigned long prev_balance_time = jiffies; + long time_remaining = balanced_irq_interval; + + daemonize("kirqd"); + + /* push everything to CPU 0 to give us a starting point. */ + for (i = 0 ; i < NR_IRQS ; i++) { + pending_irq_balance_cpumask[i] = cpumask_of_cpu(0); + } + for ( ; ; ) { + set_current_state(TASK_INTERRUPTIBLE); + time_remaining = schedule_timeout(time_remaining); + try_to_freeze(PF_FREEZE); + if (time_after(jiffies, + prev_balance_time+balanced_irq_interval)) { + do_irq_balance(); + prev_balance_time = jiffies; + time_remaining = balanced_irq_interval; + } + } + return 0; +} -static int __init ioapic_pirq_setup(char *str) +static int __init balanced_irq_init(void) { - int i, max; - int ints[MAX_PIRQS+1]; + int i; + struct cpuinfo_x86 *c; + cpumask_t tmp; + + cpus_shift_right(tmp, cpu_online_map, 2); + c = &boot_cpu_data; + /* When not overwritten by the command line ask subarchitecture. */ + if (irqbalance_disabled == IRQBALANCE_CHECK_ARCH) + irqbalance_disabled = NO_BALANCE_IRQ; + if (irqbalance_disabled) + return 0; + + /* disable irqbalance completely if there is only one processor online */ + if (num_online_cpus() < 2) { + irqbalance_disabled = 1; + return 0; + } + /* + * Enable physical balance only if more than 1 physical processor + * is present + */ + if (smp_num_siblings > 1 && !cpus_empty(tmp)) + physical_balance = 1; - get_options(str, ARRAY_SIZE(ints), ints); + for (i = 0; i < NR_CPUS; i++) { + if (!cpu_online(i)) + continue; + irq_cpu_data[i].irq_delta = kmalloc(sizeof(unsigned long) * NR_IRQS, GFP_KERNEL); + irq_cpu_data[i].last_irq = kmalloc(sizeof(unsigned long) * NR_IRQS, GFP_KERNEL); + if (irq_cpu_data[i].irq_delta == NULL || irq_cpu_data[i].last_irq == NULL) { + printk(KERN_ERR "balanced_irq_init: out of memory"); + goto failed; + } + memset(irq_cpu_data[i].irq_delta,0,sizeof(unsigned long) * NR_IRQS); + memset(irq_cpu_data[i].last_irq,0,sizeof(unsigned long) * NR_IRQS); + } + + printk(KERN_INFO "Starting balanced_irq\n"); + if (kernel_thread(balanced_irq, NULL, CLONE_KERNEL) >= 0) + return 0; + else + printk(KERN_ERR "balanced_irq_init: failed to spawn balanced_irq"); +failed: + for (i = 0; i < NR_CPUS; i++) { + if(irq_cpu_data[i].irq_delta) + kfree(irq_cpu_data[i].irq_delta); + if(irq_cpu_data[i].last_irq) + kfree(irq_cpu_data[i].last_irq); + } + return 0; +} - for (i = 0; i < MAX_PIRQS; i++) - pirq_entries[i] = -1; +int __init irqbalance_disable(char *str) +{ + irqbalance_disabled = 1; + return 0; +} - pirqs_enabled = 1; - printk(KERN_INFO "PIRQ redirection, working around broken MP-BIOS.\n"); - max = MAX_PIRQS; - if (ints[0] < MAX_PIRQS) - max = ints[0]; +__setup("noirqbalance", irqbalance_disable); - for (i = 0; i < max; i++) { - printk(KERN_DEBUG "... PIRQ%d -> IRQ %d\n", i, ints[i+1]); - /* - * PIRQs are mapped upside down, usually. - */ - pirq_entries[MAX_PIRQS-i-1] = ints[i+1]; +static inline void move_irq(int irq) +{ + /* note - we hold the desc->lock */ + if (unlikely(!cpus_empty(pending_irq_balance_cpumask[irq]))) { + set_ioapic_affinity_irq(irq, pending_irq_balance_cpumask[irq]); + cpus_clear(pending_irq_balance_cpumask[irq]); } - return 1; } -__setup("pirq=", ioapic_pirq_setup); +late_initcall(balanced_irq_init); -#endif +#else /* !CONFIG_IRQBALANCE */ +static inline void move_irq(int irq) { } +#endif /* CONFIG_IRQBALANCE */ + +#ifndef CONFIG_SMP +void fastcall send_IPI_self(int vector) +{ + unsigned int cfg; + + /* + * Wait for idle. + */ + apic_wait_icr_idle(); + cfg = APIC_DM_FIXED | APIC_DEST_SELF | vector | APIC_DEST_LOGICAL; + /* + * Send the IPI. The write to APIC_ICR fires this off. + */ + apic_write_around(APIC_ICR, cfg); +} +#endif /* !CONFIG_SMP */ /* * Find the IRQ entry number of a certain pin. */ -static int __init find_irq_entry(int apic, int pin, int type) +static int find_irq_entry(int apic, int pin, int type) { int i; @@ -289,7 +685,7 @@ static int __init find_irq_entry(int apic, int pin, int type) /* * Find the pin to which IRQ[irq] (ISA) is connected */ -static int __init find_isa_irq_pin(int irq, int type) +static int find_isa_irq_pin(int irq, int type) { int i; @@ -298,7 +694,9 @@ static int __init find_isa_irq_pin(int irq, int type) if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA || mp_bus_id_to_type[lbus] == MP_BUS_EISA || - mp_bus_id_to_type[lbus] == MP_BUS_MCA) && + mp_bus_id_to_type[lbus] == MP_BUS_MCA || + mp_bus_id_to_type[lbus] == MP_BUS_NEC98 + ) && (mp_irqs[i].mpc_irqtype == type) && (mp_irqs[i].mpc_srcbusirq == irq)) @@ -313,16 +711,81 @@ static int __init find_isa_irq_pin(int irq, int type) */ static int pin_2_irq(int idx, int apic, int pin); +int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin) +{ + int apic, i, best_guess = -1; + + apic_printk(APIC_DEBUG, "querying PCI -> IRQ mapping bus:%d, " + "slot:%d, pin:%d.\n", bus, slot, pin); + if (mp_bus_id_to_pci_bus[bus] == -1) { + printk(KERN_WARNING "PCI BIOS passed nonexistent PCI bus %d!\n", bus); + return -1; + } + for (i = 0; i < mp_irq_entries; i++) { + int lbus = mp_irqs[i].mpc_srcbus; + + for (apic = 0; apic < nr_ioapics; apic++) + if (mp_ioapics[apic].mpc_apicid == mp_irqs[i].mpc_dstapic || + mp_irqs[i].mpc_dstapic == MP_APIC_ALL) + break; + + if ((mp_bus_id_to_type[lbus] == MP_BUS_PCI) && + !mp_irqs[i].mpc_irqtype && + (bus == lbus) && + (slot == ((mp_irqs[i].mpc_srcbusirq >> 2) & 0x1f))) { + int irq = pin_2_irq(i,apic,mp_irqs[i].mpc_dstirq); + + if (!(apic || IO_APIC_IRQ(irq))) + continue; + + if (pin == (mp_irqs[i].mpc_srcbusirq & 3)) + return irq; + /* + * Use the first all-but-pin matching entry as a + * best-guess fuzzy result for broken mptables. + */ + if (best_guess < 0) + best_guess = irq; + } + } + return best_guess; +} + +/* + * This function currently is only a helper for the i386 smp boot process where + * we need to reprogram the ioredtbls to cater for the cpus which have come online + * so mask in all cases should simply be TARGET_CPUS + */ +void __init setup_ioapic_dest(void) +{ + int pin, ioapic, irq, irq_entry; + + if (skip_ioapic_setup == 1) + return; + + for (ioapic = 0; ioapic < nr_ioapics; ioapic++) { + for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) { + irq_entry = find_irq_entry(ioapic, pin, mp_INT); + if (irq_entry == -1) + continue; + irq = pin_2_irq(irq_entry, ioapic, pin); + set_ioapic_affinity_irq(irq, TARGET_CPUS); + } + + } +} + /* * EISA Edge/Level control register, ELCR */ -static int __init EISA_ELCR(unsigned int irq) +static int EISA_ELCR(unsigned int irq) { if (irq < 16) { unsigned int port = 0x4d0 + (irq >> 3); return (inb(port) >> (irq & 7)) & 1; } - printk(KERN_INFO "Broken MPtable reports ISA irq %d\n", irq); + apic_printk(APIC_VERBOSE, KERN_INFO + "Broken MPtable reports ISA irq %d\n", irq); return 0; } @@ -352,6 +815,12 @@ static int __init EISA_ELCR(unsigned int irq) #define default_MCA_trigger(idx) (1) #define default_MCA_polarity(idx) (0) +/* NEC98 interrupts are always polarity zero edge triggered, + * when listed as conforming in the MP table. */ + +#define default_NEC98_trigger(idx) (0) +#define default_NEC98_polarity(idx) (0) + static int __init MPBIOS_polarity(int idx) { int bus = mp_irqs[idx].mpc_srcbus; @@ -386,6 +855,11 @@ static int __init MPBIOS_polarity(int idx) polarity = default_MCA_polarity(idx); break; } + case MP_BUS_NEC98: /* NEC 98 pin */ + { + polarity = default_NEC98_polarity(idx); + break; + } default: { printk(KERN_WARNING "broken BIOS!!\n"); @@ -421,7 +895,7 @@ static int __init MPBIOS_polarity(int idx) return polarity; } -static int __init MPBIOS_trigger(int idx) +static int MPBIOS_trigger(int idx) { int bus = mp_irqs[idx].mpc_srcbus; int trigger; @@ -455,6 +929,11 @@ static int __init MPBIOS_trigger(int idx) trigger = default_MCA_trigger(idx); break; } + case MP_BUS_NEC98: /* NEC 98 pin */ + { + trigger = default_NEC98_trigger(idx); + break; + } default: { printk(KERN_WARNING "broken BIOS!!\n"); @@ -516,6 +995,7 @@ static int pin_2_irq(int idx, int apic, int pin) case MP_BUS_ISA: /* ISA pin */ case MP_BUS_EISA: case MP_BUS_MCA: + case MP_BUS_NEC98: { irq = mp_irqs[idx].mpc_srcbusirq; break; @@ -529,6 +1009,13 @@ static int pin_2_irq(int idx, int apic, int pin) while (i < apic) irq += nr_ioapic_registers[i++]; irq += pin; + + /* + * For MPS mode, so far only needed by ES7000 platform + */ + if (ioapic_renumber_irq) + irq = ioapic_renumber_irq(apic, irq); + break; } default: @@ -539,20 +1026,6 @@ static int pin_2_irq(int idx, int apic, int pin) } } - /* - * PCI IRQ command line redirection. Yes, limits are hardcoded. - */ - if ((pin >= 16) && (pin <= 23)) { - if (pirq_entries[pin-16] != -1) { - if (!pirq_entries[pin-16]) { - printk(KERN_DEBUG "disabling PIRQ%d\n", pin-16); - } else { - irq = pirq_entries[pin-16]; - printk(KERN_DEBUG "using PIRQ%d -> IRQ %d\n", - pin-16, irq); - } - } - } return irq; } @@ -573,90 +1046,74 @@ static inline int IO_APIC_irq_trigger(int irq) return 0; } -int irq_vector[NR_IRQS] = { FIRST_DEVICE_VECTOR , 0 }; - -int vector_irq[256]; +/* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */ +u8 irq_vector[NR_IRQ_VECTORS] = { FIRST_DEVICE_VECTOR , 0 }; int assign_irq_vector(int irq) { static int current_vector = FIRST_DEVICE_VECTOR, offset = 0; - if (IO_APIC_VECTOR(irq) > 0) + + BUG_ON(irq >= NR_IRQ_VECTORS); + if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0) return IO_APIC_VECTOR(irq); next: current_vector += 8; - /* Skip the hypercall vector. */ - if (current_vector == HYPERCALL_VECTOR) goto next; - /* Skip the Linux/BSD fast-trap vector. */ - if (current_vector == 0x80) goto next; + /* Skip the hypercall vector. */ + if (current_vector == HYPERCALL_VECTOR) + goto next; + + /* Skip the Linux/BSD fast-trap vector. */ + if (current_vector == 0x80) + goto next; - if (current_vector > FIRST_SYSTEM_VECTOR) { + if (current_vector >= FIRST_SYSTEM_VECTOR) { offset++; + if (!(offset%8)) + return -ENOSPC; current_vector = FIRST_DEVICE_VECTOR + offset; } - if (current_vector == FIRST_SYSTEM_VECTOR) - panic("ran out of interrupt sources!"); - - IO_APIC_VECTOR(irq) = current_vector; - - vector_irq[current_vector] = irq; + vector_irq[current_vector] = irq; + if (irq != AUTO_ASSIGN) + IO_APIC_VECTOR(irq) = current_vector; return current_vector; } -extern void (*interrupt[NR_IRQS])(void); +static struct hw_interrupt_type ioapic_level_type; +static struct hw_interrupt_type ioapic_edge_type; -/* - * Level and edge triggered IO-APIC interrupts need different handling, - * so we use two separate IRQ descriptors. Edge triggered IRQs can be - * handled with the level-triggered descriptor, but that one has slightly - * more overhead. Level-triggered interrupts cannot be handled with the - * edge-triggered handler, without risking IRQ storms and other ugly - * races. - */ +#define IOAPIC_AUTO -1 +#define IOAPIC_EDGE 0 +#define IOAPIC_LEVEL 1 -static unsigned int startup_edge_ioapic_irq(unsigned int irq); -#define shutdown_edge_ioapic_irq disable_edge_ioapic_irq -#define enable_edge_ioapic_irq unmask_IO_APIC_irq -static void disable_edge_ioapic_irq (unsigned int irq); -static void ack_edge_ioapic_irq(unsigned int irq); -static void end_edge_ioapic_irq (unsigned int i); -static struct hw_interrupt_type ioapic_edge_irq_type = { - "IO-APIC-edge", - startup_edge_ioapic_irq, - shutdown_edge_ioapic_irq, - enable_edge_ioapic_irq, - disable_edge_ioapic_irq, - ack_edge_ioapic_irq, - end_edge_ioapic_irq, - set_ioapic_affinity, -}; - -static unsigned int startup_level_ioapic_irq (unsigned int irq); -#define shutdown_level_ioapic_irq mask_IO_APIC_irq -#define enable_level_ioapic_irq unmask_IO_APIC_irq -#define disable_level_ioapic_irq mask_IO_APIC_irq -static void mask_and_ack_level_ioapic_irq (unsigned int irq); -static void end_level_ioapic_irq (unsigned int irq); -static struct hw_interrupt_type ioapic_level_irq_type = { - "IO-APIC-level", - startup_level_ioapic_irq, - shutdown_level_ioapic_irq, - enable_level_ioapic_irq, - disable_level_ioapic_irq, - mask_and_ack_level_ioapic_irq, - end_level_ioapic_irq, - set_ioapic_affinity, -}; +static inline void ioapic_register_intr(int irq, int vector, unsigned long trigger) +{ + if (use_pci_vector() && !platform_legacy_irq(irq)) { + if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) || + trigger == IOAPIC_LEVEL) + irq_desc[vector].handler = &ioapic_level_type; + else + irq_desc[vector].handler = &ioapic_edge_type; + set_intr_gate(vector, interrupt[vector]); + } else { + if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) || + trigger == IOAPIC_LEVEL) + irq_desc[irq].handler = &ioapic_level_type; + else + irq_desc[irq].handler = &ioapic_edge_type; + set_intr_gate(vector, interrupt[irq]); + } +} void __init setup_IO_APIC_irqs(void) { struct IO_APIC_route_entry entry; - int apic, pin, idx, irq, vector; + int apic, pin, idx, irq, first_notcon = 1, vector; unsigned long flags; - printk(KERN_DEBUG "init IO_APIC IRQs\n"); + apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n"); for (apic = 0; apic < nr_ioapics; apic++) { for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) { @@ -667,13 +1124,24 @@ void __init setup_IO_APIC_irqs(void) memset(&entry,0,sizeof(entry)); entry.delivery_mode = INT_DELIVERY_MODE; - entry.dest_mode = (INT_DEST_ADDR_MODE != 0); + entry.dest_mode = INT_DEST_MODE; entry.mask = 0; /* enable IRQ */ - entry.dest.logical.logical_dest = target_cpus(); + entry.dest.logical.logical_dest = + cpu_mask_to_apicid(TARGET_CPUS); idx = find_irq_entry(apic,pin,mp_INT); - if (idx == -1) + if (idx == -1) { + if (first_notcon) { + apic_printk(APIC_VERBOSE, KERN_DEBUG + " IO-APIC (apicid-pin) %d-%d", + mp_ioapics[apic].mpc_apicid, + pin); + first_notcon = 0; + } else + apic_printk(APIC_VERBOSE, ", %d-%d", + mp_ioapics[apic].mpc_apicid, pin); continue; + } entry.trigger = irq_trigger(idx); entry.polarity = irq_polarity(idx); @@ -688,8 +1156,7 @@ void __init setup_IO_APIC_irqs(void) * skip adding the timer int on secondary nodes, which causes * a small but painful rift in the time-space continuum */ - if ((clustered_apic_mode == CLUSTERED_APIC_NUMAQ) - && (apic != 0) && (irq == 0)) + if (multi_timer_check(apic, irq)) continue; else add_pin_to_irq(irq, apic, pin); @@ -700,13 +1167,7 @@ void __init setup_IO_APIC_irqs(void) if (IO_APIC_IRQ(irq)) { vector = assign_irq_vector(irq); entry.vector = vector; - - if (IO_APIC_irq_trigger(irq)) - irq_desc[irq].handler = &ioapic_level_irq_type; - else - irq_desc[irq].handler = &ioapic_edge_irq_type; - - set_intr_gate(vector, interrupt[irq]); + ioapic_register_intr(irq, vector, IOAPIC_AUTO); if (!apic && (irq < 16)) disable_8259A_irq(irq); @@ -717,11 +1178,13 @@ void __init setup_IO_APIC_irqs(void) spin_unlock_irqrestore(&ioapic_lock, flags); } } + + if (!first_notcon) + apic_printk(APIC_VERBOSE, " not connected.\n"); } /* - * Set up the 8259A-master output pin as broadcast to all - * CPUs. + * Set up the 8259A-master output pin: */ void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector) { @@ -739,9 +1202,9 @@ void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector) * We use logical delivery to get the timer IRQ * to the first CPU. */ - entry.dest_mode = (INT_DEST_ADDR_MODE != 0); + entry.dest_mode = INT_DEST_MODE; entry.mask = 0; /* unmask IRQ now */ - entry.dest.logical.logical_dest = target_cpus(); + entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS); entry.delivery_mode = INT_DELIVERY_MODE; entry.polarity = 0; entry.trigger = 0; @@ -751,7 +1214,7 @@ void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector) * The timer IRQ doesn't have to know that behind the * scene we have a 8259A-master in AEOI mode ... */ - irq_desc[0].handler = &ioapic_edge_irq_type; + irq_desc[0].handler = &ioapic_edge_type; /* * Add it to the IO-APIC irq-routing table: @@ -764,23 +1227,23 @@ void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector) enable_8259A_irq(0); } -void __init UNEXPECTED_IO_APIC(void) +static inline void UNEXPECTED_IO_APIC(void) { - printk(KERN_WARNING - "An unexpected IO-APIC was found. If this kernel release is less than\n" - "three months old please report this to linux-smp@vger.kernel.org\n"); } void __init print_IO_APIC(void) { -#ifdef VERBOSE +#ifndef NDEBUG int apic, i; - struct IO_APIC_reg_00 reg_00; - struct IO_APIC_reg_01 reg_01; - struct IO_APIC_reg_02 reg_02; - struct IO_APIC_reg_03 reg_03; + union IO_APIC_reg_00 reg_00; + union IO_APIC_reg_01 reg_01; + union IO_APIC_reg_02 reg_02; + union IO_APIC_reg_03 reg_03; unsigned long flags; + if (apic_verbosity == APIC_QUIET) + return; + printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries); for (i = 0; i < nr_ioapics; i++) printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n", @@ -795,47 +1258,46 @@ void __init print_IO_APIC(void) for (apic = 0; apic < nr_ioapics; apic++) { spin_lock_irqsave(&ioapic_lock, flags); - *(int *)®_00 = io_apic_read(apic, 0); - *(int *)®_01 = io_apic_read(apic, 1); - if (reg_01.version >= 0x10) - *(int *)®_02 = io_apic_read(apic, 2); - if (reg_01.version >= 0x20) - *(int *)®_03 = io_apic_read(apic, 3); + reg_00.raw = io_apic_read(apic, 0); + reg_01.raw = io_apic_read(apic, 1); + if (reg_01.bits.version >= 0x10) + reg_02.raw = io_apic_read(apic, 2); + if (reg_01.bits.version >= 0x20) + reg_03.raw = io_apic_read(apic, 3); spin_unlock_irqrestore(&ioapic_lock, flags); - printk("\n"); printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mpc_apicid); - printk(KERN_DEBUG ".... register #00: %08X\n", *(int *)®_00); - printk(KERN_DEBUG "....... : physical APIC id: %02X\n", reg_00.ID); - printk(KERN_DEBUG "....... : Delivery Type: %X\n", reg_00.delivery_type); - printk(KERN_DEBUG "....... : LTS : %X\n", reg_00.LTS); - if (reg_00.__reserved_0 || reg_00.__reserved_1 || reg_00.__reserved_2) + printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw); + printk(KERN_DEBUG "....... : physical APIC id: %02X\n", reg_00.bits.ID); + printk(KERN_DEBUG "....... : Delivery Type: %X\n", reg_00.bits.delivery_type); + printk(KERN_DEBUG "....... : LTS : %X\n", reg_00.bits.LTS); + if (reg_00.bits.ID >= get_physical_broadcast()) + UNEXPECTED_IO_APIC(); + if (reg_00.bits.__reserved_1 || reg_00.bits.__reserved_2) UNEXPECTED_IO_APIC(); - printk(KERN_DEBUG ".... register #01: %08X\n", *(int *)®_01); - printk(KERN_DEBUG "....... : max redirection entries: %04X\n", reg_01.entries); - if ( (reg_01.entries != 0x0f) && /* older (Neptune) boards */ - (reg_01.entries != 0x17) && /* typical ISA+PCI boards */ - (reg_01.entries != 0x1b) && /* Compaq Proliant boards */ - (reg_01.entries != 0x1f) && /* dual Xeon boards */ - (reg_01.entries != 0x22) && /* bigger Xeon boards */ - (reg_01.entries != 0x2E) && - (reg_01.entries != 0x3F) + printk(KERN_DEBUG ".... register #01: %08X\n", reg_01.raw); + printk(KERN_DEBUG "....... : max redirection entries: %04X\n", reg_01.bits.entries); + if ( (reg_01.bits.entries != 0x0f) && /* older (Neptune) boards */ + (reg_01.bits.entries != 0x17) && /* typical ISA+PCI boards */ + (reg_01.bits.entries != 0x1b) && /* Compaq Proliant boards */ + (reg_01.bits.entries != 0x1f) && /* dual Xeon boards */ + (reg_01.bits.entries != 0x22) && /* bigger Xeon boards */ + (reg_01.bits.entries != 0x2E) && + (reg_01.bits.entries != 0x3F) ) UNEXPECTED_IO_APIC(); - printk(KERN_DEBUG "....... : PRQ implemented: %X\n", reg_01.PRQ); - printk(KERN_DEBUG "....... : IO APIC version: %04X\n", reg_01.version); - if ( (reg_01.version != 0x01) && /* 82489DX IO-APICs */ - (reg_01.version != 0x02) && /* VIA */ - (reg_01.version != 0x03) && /* later VIA */ - (reg_01.version != 0x10) && /* oldest IO-APICs */ - (reg_01.version != 0x11) && /* Pentium/Pro IO-APICs */ - (reg_01.version != 0x13) && /* Xeon IO-APICs */ - (reg_01.version != 0x20) /* Intel P64H (82806 AA) */ + printk(KERN_DEBUG "....... : PRQ implemented: %X\n", reg_01.bits.PRQ); + printk(KERN_DEBUG "....... : IO APIC version: %04X\n", reg_01.bits.version); + if ( (reg_01.bits.version != 0x01) && /* 82489DX IO-APICs */ + (reg_01.bits.version != 0x10) && /* oldest IO-APICs */ + (reg_01.bits.version != 0x11) && /* Pentium/Pro IO-APICs */ + (reg_01.bits.version != 0x13) && /* Xeon IO-APICs */ + (reg_01.bits.version != 0x20) /* Intel P64H (82806 AA) */ ) UNEXPECTED_IO_APIC(); - if (reg_01.__reserved_1 || reg_01.__reserved_2) + if (reg_01.bits.__reserved_1 || reg_01.bits.__reserved_2) UNEXPECTED_IO_APIC(); /* @@ -843,10 +1305,10 @@ void __init print_IO_APIC(void) * but the value of reg_02 is read as the previous read register * value, so ignore it if reg_02 == reg_01. */ - if (reg_01.version >= 0x10 && *(int *)®_02 != *(int *)®_01) { - printk(KERN_DEBUG ".... register #02: %08X\n", *(int *)®_02); - printk(KERN_DEBUG "....... : arbitration: %02X\n", reg_02.arbitration); - if (reg_02.__reserved_1 || reg_02.__reserved_2) + if (reg_01.bits.version >= 0x10 && reg_02.raw != reg_01.raw) { + printk(KERN_DEBUG ".... register #02: %08X\n", reg_02.raw); + printk(KERN_DEBUG "....... : arbitration: %02X\n", reg_02.bits.arbitration); + if (reg_02.bits.__reserved_1 || reg_02.bits.__reserved_2) UNEXPECTED_IO_APIC(); } @@ -855,11 +1317,11 @@ void __init print_IO_APIC(void) * or reg_03, but the value of reg_0[23] is read as the previous read * register value, so ignore it if reg_03 == reg_0[12]. */ - if (reg_01.version >= 0x20 && *(int *)®_03 != *(int *)®_02 && - *(int *)®_03 != *(int *)®_01) { - printk(KERN_DEBUG ".... register #03: %08X\n", *(int *)®_03); - printk(KERN_DEBUG "....... : Boot DT : %X\n", reg_03.boot_DT); - if (reg_03.__reserved_1) + if (reg_01.bits.version >= 0x20 && reg_03.raw != reg_02.raw && + reg_03.raw != reg_01.raw) { + printk(KERN_DEBUG ".... register #03: %08X\n", reg_03.raw); + printk(KERN_DEBUG "....... : Boot DT : %X\n", reg_03.bits.boot_DT); + if (reg_03.bits.__reserved_1) UNEXPECTED_IO_APIC(); } @@ -868,7 +1330,7 @@ void __init print_IO_APIC(void) printk(KERN_DEBUG " NR Log Phy Mask Trig IRR Pol" " Stat Dest Deli Vect: \n"); - for (i = 0; i <= reg_01.entries; i++) { + for (i = 0; i <= reg_01.bits.entries; i++) { struct IO_APIC_route_entry entry; spin_lock_irqsave(&ioapic_lock, flags); @@ -894,12 +1356,17 @@ void __init print_IO_APIC(void) ); } } + if (use_pci_vector()) + printk(KERN_INFO "Using vector-based indexing\n"); printk(KERN_DEBUG "IRQ to pin mappings:\n"); for (i = 0; i < NR_IRQS; i++) { struct irq_pin_list *entry = irq_2_pin + i; if (entry->pin < 0) continue; - printk(KERN_DEBUG "IRQ%d ", i); + if (use_pci_vector() && !platform_legacy_irq(i)) + printk(KERN_DEBUG "IRQ%d ", IO_APIC_VECTOR(i)); + else + printk(KERN_DEBUG "IRQ%d ", i); for (;;) { printk("-> %d:%d", entry->apic, entry->pin); if (!entry->next) @@ -910,152 +1377,13 @@ void __init print_IO_APIC(void) } printk(KERN_INFO ".................................... done.\n"); -#endif -} - - -#if 0 /* Maybe useful for debugging, but not currently used anywhere. */ - -static void print_APIC_bitfield (int base) -{ - unsigned int v; - int i, j; - - printk(KERN_DEBUG "0123456789abcdef0123456789abcdef\n" KERN_DEBUG); - for (i = 0; i < 8; i++) { - v = apic_read(base + i*0x10); - for (j = 0; j < 32; j++) { - if (v & (1< 3) /* Due to the Pentium erratum 3AP. */ - apic_write(APIC_ESR, 0); - v = apic_read(APIC_ESR); - printk(KERN_DEBUG "... APIC ESR: %08x\n", v); - } - - v = apic_read(APIC_ICR); - printk(KERN_DEBUG "... APIC ICR: %08x\n", v); - v = apic_read(APIC_ICR2); - printk(KERN_DEBUG "... APIC ICR2: %08x\n", v); - - v = apic_read(APIC_LVTT); - printk(KERN_DEBUG "... APIC LVTT: %08x\n", v); - - if (maxlvt > 3) { /* PC is LVT#4. */ - v = apic_read(APIC_LVTPC); - printk(KERN_DEBUG "... APIC LVTPC: %08x\n", v); - } - v = apic_read(APIC_LVT0); - printk(KERN_DEBUG "... APIC LVT0: %08x\n", v); - v = apic_read(APIC_LVT1); - printk(KERN_DEBUG "... APIC LVT1: %08x\n", v); - - if (maxlvt > 2) { /* ERR is LVT#3. */ - v = apic_read(APIC_LVTERR); - printk(KERN_DEBUG "... APIC LVTERR: %08x\n", v); - } - - v = apic_read(APIC_TMICT); - printk(KERN_DEBUG "... APIC TMICT: %08x\n", v); - v = apic_read(APIC_TMCCT); - printk(KERN_DEBUG "... APIC TMCCT: %08x\n", v); - v = apic_read(APIC_TDCR); - printk(KERN_DEBUG "... APIC TDCR: %08x\n", v); - printk("\n"); -} - -void print_all_local_APICs (void) -{ - smp_call_function(print_local_APIC, NULL, 1, 1); - print_local_APIC(NULL); -} - -void /*__init*/ print_PIC(void) -{ - extern spinlock_t i8259A_lock; - unsigned int v, flags; - - printk(KERN_DEBUG "\nprinting PIC contents\n"); - - spin_lock_irqsave(&i8259A_lock, flags); - - v = inb(0xa1) << 8 | inb(0x21); - printk(KERN_DEBUG "... PIC IMR: %04x\n", v); - - v = inb(0xa0) << 8 | inb(0x20); - printk(KERN_DEBUG "... PIC IRR: %04x\n", v); - - outb(0x0b,0xa0); - outb(0x0b,0x20); - v = inb(0xa0) << 8 | inb(0x20); - outb(0x0a,0xa0); - outb(0x0a,0x20); - - spin_unlock_irqrestore(&i8259A_lock, flags); - - printk(KERN_DEBUG "... PIC ISR: %04x\n", v); - - v = inb(0x4d1) << 8 | inb(0x4d0); - printk(KERN_DEBUG "... PIC ELCR: %04x\n", v); -} - -#endif /* 0 */ - - static void __init enable_IO_APIC(void) { - struct IO_APIC_reg_01 reg_01; + union IO_APIC_reg_01 reg_01; int i; unsigned long flags; @@ -1063,18 +1391,15 @@ static void __init enable_IO_APIC(void) irq_2_pin[i].pin = -1; irq_2_pin[i].next = 0; } - if (!pirqs_enabled) - for (i = 0; i < MAX_PIRQS; i++) - pirq_entries[i] = -1; /* * The number of IO-APIC IRQ registers (== #pins): */ for (i = 0; i < nr_ioapics; i++) { spin_lock_irqsave(&ioapic_lock, flags); - *(int *)®_01 = io_apic_read(i, 1); + reg_01.raw = io_apic_read(i, 1); spin_unlock_irqrestore(&ioapic_lock, flags); - nr_ioapic_registers[i] = reg_01.entries+1; + nr_ioapic_registers[i] = reg_01.bits.entries+1; } /* @@ -1103,18 +1428,22 @@ void disable_IO_APIC(void) * by Matt Domsch Tue Dec 21 12:25:05 CST 1999 */ -static void __init setup_ioapic_ids_from_mpc (void) +#ifndef CONFIG_X86_NUMAQ +static void __init setup_ioapic_ids_from_mpc(void) { - struct IO_APIC_reg_00 reg_00; - unsigned long phys_id_present_map = phys_cpu_present_map; + union IO_APIC_reg_00 reg_00; + physid_mask_t phys_id_present_map; int apic; int i; unsigned char old_id; unsigned long flags; - if (clustered_apic_mode) - /* We don't have a good way to do this yet - hack */ - phys_id_present_map = (u_long) 0xf; + /* + * This is broken; anything with a real cpu count has to + * circumvent this idiocy regardless. + */ + phys_id_present_map = ioapic_phys_id_map(phys_cpu_present_map); + /* * Set the IOAPIC ID to the value stored in the MPC table. */ @@ -1122,41 +1451,48 @@ static void __init setup_ioapic_ids_from_mpc (void) /* Read the register 0 value */ spin_lock_irqsave(&ioapic_lock, flags); - *(int *)®_00 = io_apic_read(apic, 0); + reg_00.raw = io_apic_read(apic, 0); spin_unlock_irqrestore(&ioapic_lock, flags); old_id = mp_ioapics[apic].mpc_apicid; - if (mp_ioapics[apic].mpc_apicid >= apic_broadcast_id) { + if (mp_ioapics[apic].mpc_apicid >= get_physical_broadcast()) { printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n", apic, mp_ioapics[apic].mpc_apicid); printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n", - reg_00.ID); - mp_ioapics[apic].mpc_apicid = reg_00.ID; + reg_00.bits.ID); + mp_ioapics[apic].mpc_apicid = reg_00.bits.ID; } + /* Don't check I/O APIC IDs for some xAPIC systems. They have + * no meaning without the serial APIC bus. */ + if (NO_IOAPIC_CHECK) + continue; /* * Sanity check, is the ID really free? Every APIC in a * system must have a unique ID or we get lots of nice * 'stuck on smp_invalidate_needed IPI wait' messages. - * I/O APIC IDs no longer have any meaning for xAPICs and SAPICs. */ - if ((clustered_apic_mode != CLUSTERED_APIC_XAPIC) && - (phys_id_present_map & (1 << mp_ioapics[apic].mpc_apicid))) { + if (check_apicid_used(phys_id_present_map, + mp_ioapics[apic].mpc_apicid)) { printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n", apic, mp_ioapics[apic].mpc_apicid); - for (i = 0; i < 0xf; i++) - if (!(phys_id_present_map & (1 << i))) + for (i = 0; i < get_physical_broadcast(); i++) + if (!physid_isset(i, phys_id_present_map)) break; - if (i >= apic_broadcast_id) + if (i >= get_physical_broadcast()) panic("Max APIC ID exceeded!\n"); printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n", i); - phys_id_present_map |= 1 << i; + physid_set(i, phys_id_present_map); mp_ioapics[apic].mpc_apicid = i; } else { - printk("Setting %d in the phys_id_present_map\n", mp_ioapics[apic].mpc_apicid); - phys_id_present_map |= 1 << mp_ioapics[apic].mpc_apicid; + physid_mask_t tmp; + tmp = apicid_to_cpu_present(mp_ioapics[apic].mpc_apicid); + apic_printk(APIC_VERBOSE, "Setting %d in the " + "phys_id_present_map\n", + mp_ioapics[apic].mpc_apicid); + physids_or(phys_id_present_map, phys_id_present_map, tmp); } @@ -1174,26 +1510,30 @@ static void __init setup_ioapic_ids_from_mpc (void) * Read the right value from the MPC table and * write it into the ID register. */ - printk(KERN_INFO "...changing IO-APIC physical APIC ID to %d ...", - mp_ioapics[apic].mpc_apicid); + apic_printk(APIC_VERBOSE, KERN_INFO + "...changing IO-APIC physical APIC ID to %d ...", + mp_ioapics[apic].mpc_apicid); - reg_00.ID = mp_ioapics[apic].mpc_apicid; + reg_00.bits.ID = mp_ioapics[apic].mpc_apicid; spin_lock_irqsave(&ioapic_lock, flags); - io_apic_write(apic, 0, *(int *)®_00); + io_apic_write(apic, 0, reg_00.raw); spin_unlock_irqrestore(&ioapic_lock, flags); /* * Sanity check */ spin_lock_irqsave(&ioapic_lock, flags); - *(int *)®_00 = io_apic_read(apic, 0); + reg_00.raw = io_apic_read(apic, 0); spin_unlock_irqrestore(&ioapic_lock, flags); - if (reg_00.ID != mp_ioapics[apic].mpc_apicid) - panic("could not set ID!\n"); + if (reg_00.bits.ID != mp_ioapics[apic].mpc_apicid) + printk("could not set ID!\n"); else - printk(" ok.\n"); + apic_printk(APIC_VERBOSE, " ok.\n"); } } +#else +static void __init setup_ioapic_ids_from_mpc(void) { } +#endif /* * There is a nasty bug in some older SMP boards, their mptable lies @@ -1205,9 +1545,9 @@ static void __init setup_ioapic_ids_from_mpc (void) */ static int __init timer_irq_works(void) { - unsigned int t1 = jiffies; + unsigned long t1 = jiffies; - __sti(); + local_irq_enable(); /* Let ten ticks pass... */ mdelay((10 * 1000) / HZ); @@ -1224,7 +1564,18 @@ static int __init timer_irq_works(void) return 0; } -static void disable_edge_ioapic_irq (unsigned int irq) { /* nothing */ } +/* + * In the SMP+IOAPIC case it might happen that there are an unspecified + * number of pending IRQ events unhandled. These cases are very rare, + * so we 'resend' these IRQs via IPIs, to the same CPU. It's much + * better to do it this way as thus we do not have to be aware of + * 'pending' interrupts in the IRQ path, except at this point. + */ +/* + * Edge triggered needs to resend any interrupt + * that was delayed but this is now handled in the device + * independent code. + */ /* * Starting up a edge-triggered IO-APIC interrupt is @@ -1235,7 +1586,6 @@ static void disable_edge_ioapic_irq (unsigned int irq) { /* nothing */ } * This is not complete - we should be able to fake * an edge even if it isn't on the 8259A... */ - static unsigned int startup_edge_ioapic_irq(unsigned int irq) { int was_pending = 0; @@ -1260,16 +1610,13 @@ static unsigned int startup_edge_ioapic_irq(unsigned int irq) */ static void ack_edge_ioapic_irq(unsigned int irq) { - balance_irq(irq); + move_irq(irq); if ((irq_desc[irq].status & (IRQ_PENDING | IRQ_DISABLED)) == (IRQ_PENDING | IRQ_DISABLED)) mask_IO_APIC_irq(irq); ack_APIC_irq(); } -static void end_edge_ioapic_irq (unsigned int i) { /* nothing */ } - - /* * Level triggered interrupts can just be masked, * and shutting down and starting up the interrupt @@ -1291,15 +1638,12 @@ static unsigned int startup_level_ioapic_irq (unsigned int irq) return 0; /* don't check for pending */ } -static void mask_and_ack_level_ioapic_irq(unsigned int irq) +static void end_level_ioapic_irq (unsigned int irq) { unsigned long v; int i; - balance_irq(irq); - - mask_IO_APIC_irq(irq); - + move_irq(irq); /* * It appears there is an erratum which affects at least version 0x11 * of I/O APIC (that's the 82093AA and cores integrated into various @@ -1320,45 +1664,102 @@ static void mask_and_ack_level_ioapic_irq(unsigned int irq) * The idea is from Manfred Spraul. --macro */ i = IO_APIC_VECTOR(irq); + v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1)); ack_APIC_irq(); if (!(v & (1 << (i & 0x1f)))) { -#ifdef APIC_LOCKUP_DEBUG - struct irq_pin_list *entry; -#endif - -#ifdef APIC_MISMATCH_DEBUG atomic_inc(&irq_mis_count); -#endif spin_lock(&ioapic_lock); - __edge_IO_APIC_irq(irq); -#ifdef APIC_LOCKUP_DEBUG - for (entry = irq_2_pin + irq;;) { - unsigned int reg; - - if (entry->pin == -1) - break; - reg = io_apic_read(entry->apic, 0x10 + entry->pin * 2); - if (reg & 0x00004000) - printk(KERN_CRIT "Aieee!!! Remote IRR" - " still set after unlock!\n"); - if (!entry->next) - break; - entry = irq_2_pin + entry->next; - } -#endif - __level_IO_APIC_irq(irq); + __mask_and_edge_IO_APIC_irq(irq); + __unmask_and_level_IO_APIC_irq(irq); spin_unlock(&ioapic_lock); } } -static void end_level_ioapic_irq(unsigned int irq) +#ifdef CONFIG_PCI_MSI +static unsigned int startup_edge_ioapic_vector(unsigned int vector) +{ + int irq = vector_to_irq(vector); + + return startup_edge_ioapic_irq(irq); +} + +static void ack_edge_ioapic_vector(unsigned int vector) +{ + int irq = vector_to_irq(vector); + + ack_edge_ioapic_irq(irq); +} + +static unsigned int startup_level_ioapic_vector (unsigned int vector) +{ + int irq = vector_to_irq(vector); + + return startup_level_ioapic_irq (irq); +} + +static void end_level_ioapic_vector (unsigned int vector) +{ + int irq = vector_to_irq(vector); + + end_level_ioapic_irq(irq); +} + +static void mask_IO_APIC_vector (unsigned int vector) { + int irq = vector_to_irq(vector); + + mask_IO_APIC_irq(irq); +} + +static void unmask_IO_APIC_vector (unsigned int vector) +{ + int irq = vector_to_irq(vector); + unmask_IO_APIC_irq(irq); } +static void set_ioapic_affinity_vector (unsigned int vector, + cpumask_t cpu_mask) +{ + int irq = vector_to_irq(vector); + + set_ioapic_affinity_irq(irq, cpu_mask); +} +#endif + +/* + * Level and edge triggered IO-APIC interrupts need different handling, + * so we use two separate IRQ descriptors. Edge triggered IRQs can be + * handled with the level-triggered descriptor, but that one has slightly + * more overhead. Level-triggered interrupts cannot be handled with the + * edge-triggered handler, without risking IRQ storms and other ugly + * races. + */ +static struct hw_interrupt_type ioapic_edge_type = { + .typename = "IO-APIC-edge", + .startup = startup_edge_ioapic, + .shutdown = shutdown_edge_ioapic, + .enable = enable_edge_ioapic, + .disable = disable_edge_ioapic, + .ack = ack_edge_ioapic, + .end = end_edge_ioapic, + .set_affinity = set_ioapic_affinity, +}; + +static struct hw_interrupt_type ioapic_level_type = { + .typename = "IO-APIC-level", + .startup = startup_level_ioapic, + .shutdown = shutdown_level_ioapic, + .enable = enable_level_ioapic, + .disable = disable_level_ioapic, + .ack = mask_and_ack_level_ioapic, + .end = end_level_ioapic, + .set_affinity = set_ioapic_affinity, +}; + static inline void init_IO_APIC_traps(void) { int irq; @@ -1375,7 +1776,13 @@ static inline void init_IO_APIC_traps(void) * 0x80, because int 0x80 is hm, kind of importantish. ;) */ for (irq = 0; irq < NR_IRQS ; irq++) { - if (IO_APIC_IRQ(irq) && !IO_APIC_VECTOR(irq)) { + int tmp = irq; + if (use_pci_vector()) { + if (!platform_legacy_irq(tmp)) + if ((tmp = vector_to_irq(tmp)) == -1) + continue; + } + if (IO_APIC_IRQ(tmp) && !IO_APIC_VECTOR(tmp)) { /* * Hmm.. We don't have an entry for this, * so default to an old-fashioned 8259 @@ -1414,15 +1821,35 @@ static void ack_lapic_irq (unsigned int irq) static void end_lapic_irq (unsigned int i) { /* nothing */ } static struct hw_interrupt_type lapic_irq_type = { - "local-APIC-edge", - NULL, /* startup_irq() not used for IRQ0 */ - NULL, /* shutdown_irq() not used for IRQ0 */ - enable_lapic_irq, - disable_lapic_irq, - ack_lapic_irq, - end_lapic_irq + .typename = "local-APIC-edge", + .startup = NULL, /* startup_irq() not used for IRQ0 */ + .shutdown = NULL, /* shutdown_irq() not used for IRQ0 */ + .enable = enable_lapic_irq, + .disable = disable_lapic_irq, + .ack = ack_lapic_irq, + .end = end_lapic_irq }; +#if 0 +static void setup_nmi (void) +{ + /* + * Dirty trick to enable the NMI watchdog ... + * We put the 8259A master into AEOI mode and + * unmask on all local APICs LVT0 as NMI. + * + * The idea to use the 8259A in AEOI mode ('8259A Virtual Wire') + * is from Maciej W. Rozycki - so we do not have to EOI from + * the NMI handler or the timer interrupt. + */ + apic_printk(APIC_VERBOSE, KERN_INFO "activating NMI Watchdog ..."); + + on_each_cpu(enable_NMI_through_LVT0, NULL, 1, 1); + + apic_printk(APIC_VERBOSE, " done.\n"); +} +#endif + /* * This looks a bit hackish but it's about the only one way of sending * a few INTA cycles to 8259As and any associated glue logic. ICR does @@ -1493,7 +1920,6 @@ static inline void unlock_ExtINT_logic(void) */ static inline void check_timer(void) { - extern int timer_ack; int pin1, pin2; int vector; @@ -1526,8 +1952,17 @@ static inline void check_timer(void) * Ok, does IRQ0 through the IOAPIC work? */ unmask_IO_APIC_irq(0); - if (timer_irq_works()) + if (timer_irq_works()) { +#if 0 + if (nmi_watchdog == NMI_IO_APIC) { + disable_8259A_irq(0); + setup_nmi(); + enable_8259A_irq(0); + check_nmi_watchdog(); + } +#endif return; + } clear_IO_APIC_pin(0, pin1); printk(KERN_ERR "..MP-BIOS bug: 8254 timer not connected to IO-APIC\n"); } @@ -1545,6 +1980,12 @@ static inline void check_timer(void) replace_pin_at_irq(0, 0, pin1, 0, pin2); else add_pin_to_irq(0, 0, pin2); +#if 0 + if (nmi_watchdog == NMI_IO_APIC) { + setup_nmi(); + check_nmi_watchdog(); + } +#endif return; } /* @@ -1554,6 +1995,11 @@ static inline void check_timer(void) } printk(" failed.\n"); + if (nmi_watchdog == NMI_IO_APIC) { + printk(KERN_WARNING "timer doesn't work through the IO-APIC - disabling NMI Watchdog!\n"); + nmi_watchdog = 0; + } + printk(KERN_INFO "...trying to set up timer as Virtual Wire IRQ..."); disable_8259A_irq(0); @@ -1570,6 +2016,7 @@ static inline void check_timer(void) printk(KERN_INFO "...trying to set up timer as ExtINT IRQ..."); + timer_ack = 0; init_8259A(0); make_8259A_irq(0); apic_write_around(APIC_LVT0, APIC_DM_EXTINT); @@ -1581,7 +2028,8 @@ static inline void check_timer(void) return; } printk(" failed :(.\n"); - panic("IO-APIC + timer doesn't work! pester mingo@redhat.com"); + panic("IO-APIC + timer doesn't work! Boot with apic=debug and send a " + "report. Then try booting with the 'noapic' option"); } #define NR_IOAPIC_BIOSIDS 256 @@ -1596,20 +2044,12 @@ static void store_ioapic_biosid_mapping(void) /* * - * IRQ's that are handled by the old PIC in all cases: + * IRQ's that are handled by the PIC in the MPS IOAPIC case. * - IRQ2 is the cascade IRQ, and cannot be a io-apic IRQ. * Linux doesn't really care, as it's not actually used * for any interrupt handling anyway. - * - There used to be IRQ13 here as well, but all - * MPS-compliant must not use it for FPU coupling and we - * want to use exception 16 anyway. And there are - * systems who connect it to an I/O APIC for other uses. - * Thus we don't mark it special any longer. - * - * Additionally, something is definitely wrong with irq9 - * on PIIX4 boards. */ -#define PIC_IRQS (1<<2) +#define PIC_IRQS (1 << PIC_CASCADE_IR) void __init setup_IO_APIC(void) { @@ -1617,7 +2057,11 @@ void __init setup_IO_APIC(void) enable_IO_APIC(); - io_apic_irqs = ~PIC_IRQS; + if (acpi_ioapic) + io_apic_irqs = ~0; /* all IRQs go through IOAPIC */ + else + io_apic_irqs = ~PIC_IRQS; + printk("ENABLING IO-APIC IRQs\n"); /* @@ -1632,22 +2076,17 @@ void __init setup_IO_APIC(void) print_IO_APIC(); } -#endif /* CONFIG_X86_IO_APIC */ - - - /* -------------------------------------------------------------------------- ACPI-based IOAPIC Configuration -------------------------------------------------------------------------- */ #ifdef CONFIG_ACPI_BOOT -#define IO_APIC_MAX_ID 15 - int __init io_apic_get_unique_id (int ioapic, int apic_id) { - struct IO_APIC_reg_00 reg_00; - static unsigned long apic_id_map = 0; + union IO_APIC_reg_00 reg_00; + static physid_mask_t apic_id_map = PHYSID_MASK_NONE; + physid_mask_t tmp; unsigned long flags; int i = 0; @@ -1660,38 +2099,31 @@ int __init io_apic_get_unique_id (int ioapic, int apic_id) * advantage of new APIC bus architecture. */ - if (!apic_id_map) - apic_id_map = phys_cpu_present_map; + if (physids_empty(apic_id_map)) + apic_id_map = ioapic_phys_id_map(phys_cpu_present_map); spin_lock_irqsave(&ioapic_lock, flags); - *(int *)®_00 = io_apic_read(ioapic, 0); + reg_00.raw = io_apic_read(ioapic, 0); spin_unlock_irqrestore(&ioapic_lock, flags); - if (apic_id >= IO_APIC_MAX_ID) { + if (apic_id >= get_physical_broadcast()) { printk(KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, trying " - "%d\n", ioapic, apic_id, reg_00.ID); - apic_id = reg_00.ID; - } - - /* XAPICs do not need unique IDs */ - if (clustered_apic_mode == CLUSTERED_APIC_XAPIC){ - printk(KERN_INFO "IOAPIC[%d]: Assigned apic_id %d\n", - ioapic, apic_id); - return apic_id; + "%d\n", ioapic, apic_id, reg_00.bits.ID); + apic_id = reg_00.bits.ID; } /* * Every APIC in a system must have a unique ID or we get lots of nice * 'stuck on smp_invalidate_needed IPI wait' messages. */ - if (apic_id_map & (1 << apic_id)) { + if (check_apicid_used(apic_id_map, apic_id)) { - for (i = 0; i < IO_APIC_MAX_ID; i++) { - if (!(apic_id_map & (1 << i))) + for (i = 0; i < get_physical_broadcast(); i++) { + if (!check_apicid_used(apic_id_map, i)) break; } - if (i == IO_APIC_MAX_ID) + if (i == get_physical_broadcast()) panic("Max apic_id exceeded!\n"); printk(KERN_WARNING "IOAPIC[%d]: apic_id %d already used, " @@ -1700,22 +2132,24 @@ int __init io_apic_get_unique_id (int ioapic, int apic_id) apic_id = i; } - apic_id_map |= (1 << apic_id); + tmp = apicid_to_cpu_present(apic_id); + physids_or(apic_id_map, apic_id_map, tmp); - if (reg_00.ID != apic_id) { - reg_00.ID = apic_id; + if (reg_00.bits.ID != apic_id) { + reg_00.bits.ID = apic_id; spin_lock_irqsave(&ioapic_lock, flags); - io_apic_write(ioapic, 0, *(int *)®_00); - *(int *)®_00 = io_apic_read(ioapic, 0); + io_apic_write(ioapic, 0, reg_00.raw); + reg_00.raw = io_apic_read(ioapic, 0); spin_unlock_irqrestore(&ioapic_lock, flags); /* Sanity check */ - if (reg_00.ID != apic_id) + if (reg_00.bits.ID != apic_id) panic("IOAPIC[%d]: Unable change apic_id!\n", ioapic); } - printk(KERN_INFO "IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id); + apic_printk(APIC_VERBOSE, KERN_INFO + "IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id); return apic_id; } @@ -1723,27 +2157,27 @@ int __init io_apic_get_unique_id (int ioapic, int apic_id) int __init io_apic_get_version (int ioapic) { - struct IO_APIC_reg_01 reg_01; + union IO_APIC_reg_01 reg_01; unsigned long flags; spin_lock_irqsave(&ioapic_lock, flags); - *(int *)®_01 = io_apic_read(ioapic, 1); + reg_01.raw = io_apic_read(ioapic, 1); spin_unlock_irqrestore(&ioapic_lock, flags); - return reg_01.version; + return reg_01.bits.version; } int __init io_apic_get_redir_entries (int ioapic) { - struct IO_APIC_reg_01 reg_01; + union IO_APIC_reg_01 reg_01; unsigned long flags; spin_lock_irqsave(&ioapic_lock, flags); - *(int *)®_01 = io_apic_read(ioapic, 1); + reg_01.raw = io_apic_read(ioapic, 1); spin_unlock_irqrestore(&ioapic_lock, flags); - return reg_01.entries; + return reg_01.bits.entries; } @@ -1753,7 +2187,7 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a unsigned long flags; if (!IO_APIC_IRQ(irq)) { - printk(KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0/n", + printk(KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n", ioapic); return -EINVAL; } @@ -1766,12 +2200,12 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a memset(&entry,0,sizeof(entry)); - entry.delivery_mode = dest_LowestPrio; - entry.dest_mode = INT_DELIVERY_MODE; - entry.dest.logical.logical_dest = target_cpus(); - entry.mask = 1; /* Disabled (masked) */ + entry.delivery_mode = INT_DELIVERY_MODE; + entry.dest_mode = INT_DEST_MODE; + entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS); entry.trigger = edge_level; entry.polarity = active_high_low; + entry.mask = 1; /* * IRQs < 16 are already in the irq_2_pin[] map @@ -1781,17 +2215,12 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a entry.vector = assign_irq_vector(irq); - printk(KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry (%d-%d -> 0x%x -> " - "IRQ %d Mode:%i Active:%i)\n", ioapic, - mp_ioapics[ioapic].mpc_apicid, pin, entry.vector, irq, edge_level, active_high_low); - - if (edge_level) { - irq_desc[irq].handler = &ioapic_level_irq_type; - } else { - irq_desc[irq].handler = &ioapic_edge_irq_type; - } + apic_printk(APIC_DEBUG, KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry " + "(%d-%d -> 0x%x -> IRQ %d Mode:%i Active:%i)\n", ioapic, + mp_ioapics[ioapic].mpc_apicid, pin, entry.vector, irq, + edge_level, active_high_low); - set_intr_gate(entry.vector, interrupt[irq]); + ioapic_register_intr(irq, entry.vector, edge_level); if (!ioapic && (irq < 16)) disable_8259A_irq(irq); @@ -1806,123 +2235,12 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a #endif /*CONFIG_ACPI_BOOT*/ -/* opt_leveltrigger, opt_edgetrigger: Force an IO-APIC-routed IRQ to be */ -/* level- or edge-triggered. */ -/* Example: 'leveltrigger=4,5,6,20 edgetrigger=21'. */ -static char opt_leveltrigger[30] = "", opt_edgetrigger[30] = ""; -string_param("leveltrigger", opt_leveltrigger); -string_param("edgetrigger", opt_edgetrigger); - -static int __init ioapic_trigger_setup(void) -{ - char *p; - irq_desc_t *desc; - long irq; - - p = opt_leveltrigger; - while ( *p != '\0' ) - { - irq = simple_strtol(p, &p, 10); - if ( (irq <= 0) || (irq >= NR_IRQS) ) - { - printk("IRQ '%ld' out of range in level-trigger list '%s'\n", - irq, opt_leveltrigger); - break; - } - - printk("Forcing IRQ %ld to level-trigger: ", irq); - - desc = &irq_desc[irq]; - spin_lock_irq(&desc->lock); - - if ( desc->handler == &ioapic_level_irq_type ) - { - printk("already level-triggered (no force applied).\n"); - } - else if ( desc->handler != &ioapic_edge_irq_type ) - { - printk("cannot force (can only force IO-APIC-edge IRQs).\n"); - } - else - { - desc->handler = &ioapic_level_irq_type; - __mask_IO_APIC_irq(irq); - __level_IO_APIC_irq(irq); - printk("done.\n"); - } - - spin_unlock_irq(&desc->lock); - - if ( *p == '\0' ) - break; - - if ( *p != ',' ) - { - printk("Unexpected character '%c' in level-trigger list '%s'\n", - *p, opt_leveltrigger); - break; - } - - p++; - } - - p = opt_edgetrigger; - while ( *p != '\0' ) - { - irq = simple_strtol(p, &p, 10); - if ( (irq <= 0) || (irq >= NR_IRQS) ) - { - printk("IRQ '%ld' out of range in edge-trigger list '%s'\n", - irq, opt_edgetrigger); - break; - } - - printk("Forcing IRQ %ld to edge-trigger: ", irq); - - desc = &irq_desc[irq]; - spin_lock_irq(&desc->lock); - - if ( desc->handler == &ioapic_edge_irq_type ) - { - printk("already edge-triggered (no force applied).\n"); - } - else if ( desc->handler != &ioapic_level_irq_type ) - { - printk("cannot force (can only force IO-APIC-level IRQs).\n"); - } - else - { - desc->handler = &ioapic_edge_irq_type; - __edge_IO_APIC_irq(irq); - desc->status |= IRQ_PENDING; /* may have lost a masked edge */ - printk("done.\n"); - } - - spin_unlock_irq(&desc->lock); - - if ( *p == '\0' ) - break; - - if ( *p != ',' ) - { - printk("Unexpected character '%c' in edge-trigger list '%s'\n", - *p, opt_edgetrigger); - break; - } - - p++; - } - - return 0; -} - -__initcall(ioapic_trigger_setup); int ioapic_guest_read(int apicid, int address, u32 *pval) { u32 val; int apicenum; - struct IO_APIC_reg_00 reg_00; + union IO_APIC_reg_00 reg_00; unsigned long flags; if ( (apicid >= NR_IOAPIC_BIOSIDS) || @@ -1936,9 +2254,9 @@ int ioapic_guest_read(int apicid, int address, u32 *pval) /* Rewrite APIC ID to what the BIOS originally specified. */ if ( address == 0 ) { - *(int *)®_00 = val; - reg_00.ID = apicid; - val = *(u32 *)®_00; + reg_00.raw = val; + reg_00.bits.ID = apicid; + val = reg_00.raw; } *pval = val; @@ -1974,7 +2292,7 @@ int ioapic_guest_write(int apicid, int address, u32 val) /* Set the correct irq-handling type. */ irq_desc[irq].handler = rte.trigger ? - &ioapic_level_irq_type: &ioapic_edge_irq_type; + &ioapic_level_type: &ioapic_edge_type; /* Record the pin<->irq mapping. */ for ( entry = &irq_2_pin[irq]; ; entry = &irq_2_pin[entry->next] ) diff --git a/xen/arch/x86/irq.c b/xen/arch/x86/irq.c index 86b3d7da99..aaaff647ce 100644 --- a/xen/arch/x86/irq.c +++ b/xen/arch/x86/irq.c @@ -42,7 +42,6 @@ struct hw_interrupt_type no_irq_type = { }; atomic_t irq_err_count; -atomic_t irq_mis_count; inline void disable_irq_nosync(unsigned int irq) { diff --git a/xen/arch/x86/microcode.c b/xen/arch/x86/microcode.c index d811e7ed70..4cbafae1e6 100644 --- a/xen/arch/x86/microcode.c +++ b/xen/arch/x86/microcode.c @@ -87,13 +87,6 @@ #define vmalloc(_s) xmalloc_bytes(_s) #define vfree(_p) xfree(_p) #define num_online_cpus() smp_num_cpus -static inline int on_each_cpu( - void (*func) (void *info), void *info, int retry, int wait) -{ - int ret = smp_call_function(func, info, retry, wait); - func(info); - return ret; -} #if 0 MODULE_DESCRIPTION("Intel CPU (IA-32) Microcode Update Driver"); diff --git a/xen/arch/x86/mpparse.c b/xen/arch/x86/mpparse.c index 6b4599fdf4..39a7619edc 100644 --- a/xen/arch/x86/mpparse.c +++ b/xen/arch/x86/mpparse.c @@ -1,5 +1,5 @@ /* - * Intel Multiprocessor Specificiation 1.1 and 1.4 + * Intel Multiprocessor Specification 1.1 and 1.4 * compliant MP-table parsing routines. * * (c) 1995 Alan Cox, Building #3 @@ -14,44 +14,48 @@ */ #include -#include -#include -#include +#include #include -#include -#include +#include #include +#include +#include + +#include +#include +#include #include -#include -#include +#include #include -#include -#include +#include -int numnodes = 1; /* XXX Xen */ +#include +#include +#include + +#define es7000_plat 0 /* XXX XEN */ /* Have we found an MP table */ int smp_found_config; +unsigned int __initdata maxcpus = NR_CPUS; /* * Various Linux-internal data structures created from the * MP-table. */ int apic_version [MAX_APICS]; +int mp_bus_id_to_type [MAX_MP_BUSSES]; +int mp_bus_id_to_node [MAX_MP_BUSSES]; +int mp_bus_id_to_local [MAX_MP_BUSSES]; int quad_local_to_mp_bus_id [NR_CPUS/4][4]; +int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 }; int mp_current_pci_id; -int *mp_bus_id_to_type; -int *mp_bus_id_to_node; -int *mp_bus_id_to_local; -int *mp_bus_id_to_pci_bus; -int max_mp_busses; -int max_irq_sources; /* I/O APIC entries */ struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS]; /* # of MP IRQ source entries */ -struct mpc_config_intsrc *mp_irqs; +struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES]; /* MP IRQ source entries */ int mp_irq_entries; @@ -65,24 +69,18 @@ unsigned long mp_lapic_addr; unsigned int boot_cpu_physical_apicid = -1U; unsigned int boot_cpu_logical_apicid = -1U; /* Internal processor count */ -static unsigned int num_processors; +static unsigned int __initdata num_processors; /* Bitmask of physically existing CPUs */ -unsigned long phys_cpu_present_map; -unsigned long logical_cpu_present_map; +physid_mask_t phys_cpu_present_map; -#ifdef CONFIG_X86_CLUSTERED_APIC -unsigned char esr_disable = 0; -unsigned char clustered_apic_mode = CLUSTERED_APIC_NONE; -unsigned int apic_broadcast_id = APIC_BROADCAST_ID_APIC; -#endif -unsigned char raw_phys_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID }; +u8 bios_cpu_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID }; /* * Intel MP BIOS table parsing routines: */ -#ifndef CONFIG_X86_VISWS_APIC + /* * Checksum an MP configuration block. */ @@ -98,48 +96,6 @@ static int __init mpf_checksum(unsigned char *mp, int len) } /* - * Processor encoding in an MP configuration block - */ - -static char __init *mpc_family(int family,int model) -{ - static char n[32]; - static char *model_defs[]= - { - "80486DX","80486DX", - "80486SX","80486DX/2 or 80487", - "80486SL","80486SX/2", - "Unknown","80486DX/2-WB", - "80486DX/4","80486DX/4-WB" - }; - - switch (family) { - case 0x04: - if (model < 10) - return model_defs[model]; - break; - - case 0x05: - return("Pentium(tm)"); - - case 0x06: - return("Pentium(tm) Pro"); - - case 0x0F: - if (model == 0x00) - return("Pentium 4(tm)"); - if (model == 0x01) - return("Pentium 4(tm)"); - if (model == 0x02) - return("Pentium 4(tm) XEON(tm)"); - if (model == 0x0F) - return("Special controller"); - } - sprintf(n,"Unknown CPU [%d:%d]",family, model); - return n; -} - -/* * Have to match translation table entries to main table entries by counter * hence the mpc_record variable .... can't see a less disgusting way of * doing this .... @@ -148,30 +104,30 @@ static char __init *mpc_family(int family,int model) static int mpc_record; static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY] __initdata; +#ifdef CONFIG_X86_NUMAQ +static int MP_valid_apicid(int apicid, int version) +{ + return hweight_long(apicid & 0xf) == 1 && (apicid >> 4) != 0xf; +} +#else +static int MP_valid_apicid(int apicid, int version) +{ + if (version >= 0x14) + return apicid < 0xff; + else + return apicid < 0xf; +} +#endif + void __init MP_processor_info (struct mpc_config_processor *m) { - int ver, quad, logical_apicid; + int ver, apicid; + physid_mask_t tmp; if (!(m->mpc_cpuflag & CPU_ENABLED)) return; - logical_apicid = m->mpc_apicid; - if (clustered_apic_mode == CLUSTERED_APIC_NUMAQ) { - quad = translation_table[mpc_record]->trans_quad; - logical_apicid = (quad << 4) + - (m->mpc_apicid ? m->mpc_apicid << 1 : 1); - printk("Processor #%d %s APIC version %d (quad %d, apic %d)\n", - m->mpc_apicid, - mpc_family((m->mpc_cpufeature & CPU_FAMILY_MASK)>>8 , - (m->mpc_cpufeature & CPU_MODEL_MASK)>>4), - m->mpc_apicver, quad, logical_apicid); - } else { - printk("Processor #%d %s APIC version %d\n", - m->mpc_apicid, - mpc_family((m->mpc_cpufeature & CPU_FAMILY_MASK)>>8 , - (m->mpc_cpufeature & CPU_MODEL_MASK)>>4), - m->mpc_apicver); - } + apicid = mpc_apic_id(m, translation_table[mpc_record]); if (m->mpc_featureflag&(1<<0)) Dprintk(" Floating point unit present.\n"); @@ -224,68 +180,68 @@ void __init MP_processor_info (struct mpc_config_processor *m) if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) { Dprintk(" Bootup CPU\n"); boot_cpu_physical_apicid = m->mpc_apicid; - boot_cpu_logical_apicid = logical_apicid; + boot_cpu_logical_apicid = apicid; } - if (num_processors >= NR_CPUS){ - printk(KERN_WARNING "NR_CPUS limit of %i reached. Cannot " - "boot CPU(apicid 0x%x).\n", NR_CPUS, m->mpc_apicid); + if (num_processors >= NR_CPUS) { + printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached." + " Processor ignored.\n", NR_CPUS); + return; + } + + if (num_processors >= maxcpus) { + printk(KERN_WARNING "WARNING: maxcpus limit of %i reached." + " Processor ignored.\n", maxcpus); return; } num_processors++; + ver = m->mpc_apicver; - if (m->mpc_apicid > MAX_APICS) { - printk("Processor #%d INVALID. (Max ID: %d).\n", + if (!MP_valid_apicid(apicid, ver)) { + printk(KERN_WARNING "Processor #%d INVALID. (Max ID: %d).\n", m->mpc_apicid, MAX_APICS); --num_processors; return; } - ver = m->mpc_apicver; - logical_cpu_present_map |= 1 << (num_processors-1); - phys_cpu_present_map |= apicid_to_phys_cpu_present(m->mpc_apicid); - + tmp = apicid_to_cpu_present(apicid); + physids_or(phys_cpu_present_map, phys_cpu_present_map, tmp); + /* * Validate version */ if (ver == 0x0) { - printk("BIOS bug, APIC version is 0 for CPU#%d! fixing up to 0x10. (tell your hw vendor)\n", m->mpc_apicid); + printk(KERN_WARNING "BIOS bug, APIC version is 0 for CPU#%d! fixing up to 0x10. (tell your hw vendor)\n", m->mpc_apicid); ver = 0x10; } apic_version[m->mpc_apicid] = ver; - raw_phys_apicid[num_processors - 1] = m->mpc_apicid; + bios_cpu_apicid[num_processors - 1] = m->mpc_apicid; } static void __init MP_bus_info (struct mpc_config_bus *m) { char str[7]; - int quad; memcpy(str, m->mpc_bustype, 6); str[6] = 0; - - if (clustered_apic_mode == CLUSTERED_APIC_NUMAQ) { - quad = translation_table[mpc_record]->trans_quad; - mp_bus_id_to_node[m->mpc_busid] = quad; - mp_bus_id_to_local[m->mpc_busid] = translation_table[mpc_record]->trans_local; - quad_local_to_mp_bus_id[quad][translation_table[mpc_record]->trans_local] = m->mpc_busid; - printk("Bus #%d is %s (node %d)\n", m->mpc_busid, str, quad); - } else { - Dprintk("Bus #%d is %s\n", m->mpc_busid, str); - } + + mpc_oem_bus_info(m, str, translation_table[mpc_record]); if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA)-1) == 0) { mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA; } else if (strncmp(str, BUSTYPE_EISA, sizeof(BUSTYPE_EISA)-1) == 0) { mp_bus_id_to_type[m->mpc_busid] = MP_BUS_EISA; } else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI)-1) == 0) { + mpc_oem_pci_bus(m, translation_table[mpc_record]); mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI; mp_bus_id_to_pci_bus[m->mpc_busid] = mp_current_pci_id; mp_current_pci_id++; } else if (strncmp(str, BUSTYPE_MCA, sizeof(BUSTYPE_MCA)-1) == 0) { mp_bus_id_to_type[m->mpc_busid] = MP_BUS_MCA; + } else if (strncmp(str, BUSTYPE_NEC98, sizeof(BUSTYPE_NEC98)-1) == 0) { + mp_bus_id_to_type[m->mpc_busid] = MP_BUS_NEC98; } else { - printk("Unknown bustype %s - ignoring\n", str); + printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str); } } @@ -294,10 +250,10 @@ static void __init MP_ioapic_info (struct mpc_config_ioapic *m) if (!(m->mpc_flags & MPC_APIC_USABLE)) return; - printk("I/O APIC #%d Version %d at 0x%X.\n", + printk(KERN_INFO "I/O APIC #%d Version %d at 0x%X.\n", m->mpc_apicid, m->mpc_apicver, m->mpc_apicaddr); if (nr_ioapics >= MAX_IO_APICS) { - printk("Max # of I/O APICs (%d) exceeded (found %d).\n", + printk(KERN_CRIT "Max # of I/O APICs (%d) exceeded (found %d).\n", MAX_IO_APICS, nr_ioapics); panic("Recompile kernel with bigger MAX_IO_APICS!.\n"); } @@ -318,7 +274,7 @@ static void __init MP_intsrc_info (struct mpc_config_intsrc *m) m->mpc_irqtype, m->mpc_irqflag & 3, (m->mpc_irqflag >> 2) & 3, m->mpc_srcbus, m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq); - if (++mp_irq_entries == max_irq_sources) + if (++mp_irq_entries == MAX_IRQ_SOURCES) panic("Max # of irq sources exceeded!!\n"); } @@ -344,16 +300,17 @@ static void __init MP_lintsrc_info (struct mpc_config_lintsrc *m) BUG(); } +#ifdef CONFIG_X86_NUMAQ static void __init MP_translation_info (struct mpc_config_translation *m) { - printk("Translation: record %d, type %d, quad %d, global %d, local %d\n", mpc_record, m->trans_type, m->trans_quad, m->trans_global, m->trans_local); + printk(KERN_INFO "Translation: record %d, type %d, quad %d, global %d, local %d\n", mpc_record, m->trans_type, m->trans_quad, m->trans_global, m->trans_local); if (mpc_record >= MAX_MPC_ENTRY) - printk("MAX_MPC_ENTRY exceeded!\n"); + printk(KERN_ERR "MAX_MPC_ENTRY exceeded!\n"); else translation_table[mpc_record] = m; /* stash this for later */ - if (m->trans_quad+1 > numnodes) - numnodes = m->trans_quad+1; + if (m->trans_quad < MAX_NUMNODES && !node_online(m->trans_quad)) + node_set_online(m->trans_quad); } /* @@ -366,10 +323,11 @@ static void __init smp_read_mpc_oem(struct mp_config_oemtable *oemtable, \ int count = sizeof (*oemtable); /* the header size */ unsigned char *oemptr = ((unsigned char *)oemtable)+count; - printk("Found an OEM MPC table at %8p - parsing it ... \n", oemtable); + mpc_record = 0; + printk(KERN_INFO "Found an OEM MPC table at %8p - parsing it ... \n", oemtable); if (memcmp(oemtable->oem_signature,MPC_OEM_SIGNATURE,4)) { - printk("SMP mpc oemtable: bad signature [%c%c%c%c]!\n", + printk(KERN_WARNING "SMP mpc oemtable: bad signature [%c%c%c%c]!\n", oemtable->oem_signature[0], oemtable->oem_signature[1], oemtable->oem_signature[2], @@ -378,7 +336,7 @@ static void __init smp_read_mpc_oem(struct mp_config_oemtable *oemtable, \ } if (mpf_checksum((unsigned char *)oemtable,oemtable->oem_length)) { - printk("SMP oem mptable: checksum error!\n"); + printk(KERN_WARNING "SMP oem mptable: checksum error!\n"); return; } while (count < oemtable->oem_length) { @@ -395,36 +353,42 @@ static void __init smp_read_mpc_oem(struct mp_config_oemtable *oemtable, \ } default: { - printk("Unrecognised OEM table entry type! - %d\n", (int) *oemptr); + printk(KERN_WARNING "Unrecognised OEM table entry type! - %d\n", (int) *oemptr); return; } } } } +static inline void mps_oem_check(struct mp_config_table *mpc, char *oem, + char *productid) +{ + if (strncmp(oem, "IBM NUMA", 8)) + printk("Warning! May not be a NUMA-Q system!\n"); + if (mpc->mpc_oemptr) + smp_read_mpc_oem((struct mp_config_oemtable *) mpc->mpc_oemptr, + mpc->mpc_oemsize); +} +#endif /* CONFIG_X86_NUMAQ */ + /* * Read/parse the MPC */ static int __init smp_read_mpc(struct mp_config_table *mpc) { - char oem[16], prod[14]; + char str[16]; + char oem[10]; int count=sizeof(*mpc); unsigned char *mpt=((unsigned char *)mpc)+count; - int num_bus = 0; - int num_irq = 0; - unsigned char *bus_data; if (memcmp(mpc->mpc_signature,MPC_SIGNATURE,4)) { - panic("SMP mptable: bad signature [%c%c%c%c]!\n", - mpc->mpc_signature[0], - mpc->mpc_signature[1], - mpc->mpc_signature[2], - mpc->mpc_signature[3]); + printk(KERN_ERR "SMP mptable: bad signature [0x%x]!\n", + *(u32 *)mpc->mpc_signature); return 0; } if (mpf_checksum((unsigned char *)mpc,mpc->mpc_length)) { - panic("SMP mptable: checksum error!\n"); + printk(KERN_ERR "SMP mptable: checksum error!\n"); return 0; } if (mpc->mpc_spec!=0x01 && mpc->mpc_spec!=0x04) { @@ -438,14 +402,14 @@ static int __init smp_read_mpc(struct mp_config_table *mpc) } memcpy(oem,mpc->mpc_oem,8); oem[8]=0; - printk("OEM ID: %s ",oem); + printk(KERN_INFO "OEM ID: %s ",oem); - memcpy(prod,mpc->mpc_productid,12); - prod[12]=0; - printk("Product ID: %s ",prod); + memcpy(str,mpc->mpc_productid,12); + str[12]=0; + printk("Product ID: %s ",str); + + mps_oem_check(mpc, oem, str); - detect_clustered_apic(oem, prod); - printk("APIC at: 0x%X\n",mpc->mpc_lapic); /* @@ -455,77 +419,10 @@ static int __init smp_read_mpc(struct mp_config_table *mpc) if (!acpi_lapic) mp_lapic_addr = mpc->mpc_lapic; - if ((clustered_apic_mode == CLUSTERED_APIC_NUMAQ) && mpc->mpc_oemptr) { - /* We need to process the oem mpc tables to tell us which quad things are in ... */ - mpc_record = 0; - smp_read_mpc_oem((struct mp_config_oemtable *)(unsigned long)mpc->mpc_oemptr, mpc->mpc_oemsize); - mpc_record = 0; - } - - /* Pre-scan to determine the number of bus and - * interrupts records we have - */ - while (count < mpc->mpc_length) { - switch (*mpt) { - case MP_PROCESSOR: - mpt += sizeof(struct mpc_config_processor); - count += sizeof(struct mpc_config_processor); - break; - case MP_BUS: - ++num_bus; - mpt += sizeof(struct mpc_config_bus); - count += sizeof(struct mpc_config_bus); - break; - case MP_INTSRC: - ++num_irq; - mpt += sizeof(struct mpc_config_intsrc); - count += sizeof(struct mpc_config_intsrc); - break; - case MP_IOAPIC: - mpt += sizeof(struct mpc_config_ioapic); - count += sizeof(struct mpc_config_ioapic); - break; - case MP_LINTSRC: - mpt += sizeof(struct mpc_config_lintsrc); - count += sizeof(struct mpc_config_lintsrc); - break; - default: - count = mpc->mpc_length; - break; - } - } - /* - * Paranoia: Allocate one extra of both the number of busses and number - * of irqs, and make sure that we have at least 4 interrupts per PCI - * slot. But some machines do not report very many busses, so we need - * to fall back on the older defaults. - */ - ++num_bus; - max_mp_busses = max(num_bus, MAX_MP_BUSSES); - if (num_irq < (4 * max_mp_busses)) - num_irq = 4 * num_bus; /* 4 intr/PCI slot */ - ++num_irq; - max_irq_sources = max(num_irq, MAX_IRQ_SOURCES); - - count = (max_mp_busses * sizeof(int)) * 4; - count += (max_irq_sources * sizeof(struct mpc_config_intsrc)); - bus_data = (void *)alloc_xenheap_pages(get_order(count)); - if (!bus_data) { - printk(KERN_ERR "SMP mptable: out of memory!\n"); - return 0; - } - mp_bus_id_to_type = (int *)&bus_data[0]; - mp_bus_id_to_node = (int *)&bus_data[(max_mp_busses * sizeof(int))]; - mp_bus_id_to_local = (int *)&bus_data[(max_mp_busses * sizeof(int)) * 2]; - mp_bus_id_to_pci_bus = (int *)&bus_data[(max_mp_busses * sizeof(int)) * 3]; - mp_irqs = (struct mpc_config_intsrc *)&bus_data[(max_mp_busses * sizeof(int)) * 4]; - memset(mp_bus_id_to_pci_bus, -1, max_mp_busses * sizeof(int)); - /* * Now process the configuration blocks. */ - count = sizeof(*mpc); - mpt = ((unsigned char *)mpc)+count; + mpc_record = 0; while (count < mpc->mpc_length) { switch(*mpt) { case MP_PROCESSOR: @@ -584,21 +481,7 @@ static int __init smp_read_mpc(struct mp_config_table *mpc) } ++mpc_record; } - - if (clustered_apic_mode){ - phys_cpu_present_map = logical_cpu_present_map; - } - - - printk("Enabling APIC mode: "); - if(clustered_apic_mode == CLUSTERED_APIC_NUMAQ) - printk("Clustered Logical. "); - else if(clustered_apic_mode == CLUSTERED_APIC_XAPIC) - printk("Physical. "); - else - printk("Flat. "); - printk("Using %d I/O APICs\n",nr_ioapics); - + clustered_apic_check(); if (!num_processors) printk(KERN_ERR "SMP mptable: no processors registered!\n"); return num_processors; @@ -634,12 +517,12 @@ static void __init construct_default_ioirq_mptable(int mpc_default_type) * If it does, we assume it's valid. */ if (mpc_default_type == 5) { - printk("ISA/PCI bus type with no IRQ information... falling back to ELCR\n"); + printk(KERN_INFO "ISA/PCI bus type with no IRQ information... falling back to ELCR\n"); if (ELCR_trigger(0) || ELCR_trigger(1) || ELCR_trigger(2) || ELCR_trigger(13)) - printk("ELCR contains invalid data... not using ELCR\n"); + printk(KERN_WARNING "ELCR contains invalid data... not using ELCR\n"); else { - printk("Using ELCR to identify PCI interrupts\n"); + printk(KERN_INFO "Using ELCR to identify PCI interrupts\n"); ELCR_fallback = 1; } } @@ -686,24 +569,6 @@ static inline void __init construct_default_ISA_mptable(int mpc_default_type) struct mpc_config_lintsrc lintsrc; int linttypes[2] = { mp_ExtINT, mp_NMI }; int i; - struct { - int mp_bus_id_to_type[MAX_MP_BUSSES]; - int mp_bus_id_to_node[MAX_MP_BUSSES]; - int mp_bus_id_to_local[MAX_MP_BUSSES]; - int mp_bus_id_to_pci_bus[MAX_MP_BUSSES]; - struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES]; - } *bus_data; - - bus_data = (void *)alloc_xenheap_pages(get_order(sizeof(*bus_data))); - if (!bus_data) - panic("SMP mptable: out of memory!\n"); - mp_bus_id_to_type = bus_data->mp_bus_id_to_type; - mp_bus_id_to_node = bus_data->mp_bus_id_to_node; - mp_bus_id_to_local = bus_data->mp_bus_id_to_local; - mp_bus_id_to_pci_bus = bus_data->mp_bus_id_to_pci_bus; - mp_irqs = bus_data->mp_irqs; - for (i = 0; i < MAX_MP_BUSSES; ++i) - mp_bus_id_to_pci_bus[i] = -1; /* * local APIC has default address @@ -732,7 +597,8 @@ static inline void __init construct_default_ISA_mptable(int mpc_default_type) bus.mpc_busid = 0; switch (mpc_default_type) { default: - printk("???\nUnknown standard configuration %d\n", + printk("???\n"); + printk(KERN_ERR "Unknown standard configuration %d\n", mpc_default_type); /* fall through */ case 1: @@ -790,7 +656,7 @@ void __init get_smp_config (void) /* * ACPI may be used to obtain the entire SMP configuration or just to - * enumerate/configure processors (CONFIG_ACPI_HT_ONLY). Note that + * enumerate/configure processors (CONFIG_ACPI_BOOT). Note that * ACPI supports both logical (e.g. Hyper-Threading) and physical * processors, where MPS only supports physical. */ @@ -801,12 +667,12 @@ void __init get_smp_config (void) else if (acpi_lapic) printk(KERN_INFO "Using ACPI for processor (LAPIC) configuration information\n"); - printk("Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification); + printk(KERN_INFO "Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification); if (mpf->mpf_feature2 & (1<<7)) { - printk(" IMCR and PIC compatibility mode.\n"); + printk(KERN_INFO " IMCR and PIC compatibility mode.\n"); pic_mode = 1; } else { - printk(" Virtual Wire compatibility mode.\n"); + printk(KERN_INFO " Virtual Wire compatibility mode.\n"); pic_mode = 0; } @@ -815,7 +681,7 @@ void __init get_smp_config (void) */ if (mpf->mpf_feature1 != 0) { - printk("Default MP configuration #%d\n", mpf->mpf_feature1); + printk(KERN_INFO "Default MP configuration #%d\n", mpf->mpf_feature1); construct_default_ISA_mptable(mpf->mpf_feature1); } else if (mpf->mpf_physptr) { @@ -824,7 +690,7 @@ void __init get_smp_config (void) * Read the physical hardware table. Anything here will * override the defaults. */ - if (!smp_read_mpc((void *)(unsigned long)mpf->mpf_physptr)) { + if (!smp_read_mpc((void *)mpf->mpf_physptr)) { smp_found_config = 0; printk(KERN_ERR "BIOS bug, MP table errors detected!...\n"); printk(KERN_ERR "... disabling SMP support. (tell your hw vendor)\n"); @@ -838,7 +704,7 @@ void __init get_smp_config (void) if (!mp_irq_entries) { struct mpc_config_bus bus; - printk("BIOS bug, no explicit IRQ entries, using default mptable. (tell your hw vendor)\n"); + printk(KERN_ERR "BIOS bug, no explicit IRQ entries, using default mptable. (tell your hw vendor)\n"); bus.mpc_type = MP_BUS; bus.mpc_busid = 0; @@ -851,7 +717,7 @@ void __init get_smp_config (void) } else BUG(); - printk("Processors: %d\n", num_processors); + printk(KERN_INFO "Processors: %d\n", num_processors); /* * Only use the first configuration found. */ @@ -859,7 +725,7 @@ void __init get_smp_config (void) static int __init smp_scan_config (unsigned long base, unsigned long length) { - unsigned int *bp = phys_to_virt(base); + unsigned long *bp = phys_to_virt(base); struct intel_mp_floating *mpf; Dprintk("Scan SMP from %p for %ld bytes.\n", bp,length); @@ -875,11 +741,27 @@ static int __init smp_scan_config (unsigned long base, unsigned long length) || (mpf->mpf_specification == 4)) ) { smp_found_config = 1; - printk("found SMP MP-table at %08lx\n", + printk(KERN_INFO "found SMP MP-table at %08lx\n", virt_to_phys(mpf)); +#if 0 reserve_bootmem(virt_to_phys(mpf), PAGE_SIZE); - if (mpf->mpf_physptr) - reserve_bootmem((unsigned long)mpf->mpf_physptr, PAGE_SIZE); + if (mpf->mpf_physptr) { + /* + * We cannot access to MPC table to compute + * table size yet, as only few megabytes from + * the bottom is mapped now. + * PC-9800's MPC table places on the very last + * of physical memory; so that simply reserving + * PAGE_SIZE from mpg->mpf_physptr yields BUG() + * in reserve_bootmem. + */ + unsigned long size = PAGE_SIZE; + unsigned long end = max_low_pfn * PAGE_SIZE; + if (mpf->mpf_physptr + size > end) + size = end - mpf->mpf_physptr; + reserve_bootmem(mpf->mpf_physptr, size); + } +#endif mpf_found = mpf; return 1; } @@ -889,7 +771,7 @@ static int __init smp_scan_config (unsigned long base, unsigned long length) return 0; } -void __init find_intel_smp (void) +void __init find_smp_config (void) { unsigned int address; @@ -913,53 +795,20 @@ void __init find_intel_smp (void) * there is a real-mode segmented pointer pointing to the * 4K EBDA area at 0x40E, calculate and scan it here. * - * NOTE! There were Linux loaders that will corrupt the EBDA + * NOTE! There are Linux loaders that will corrupt the EBDA * area, and as such this kind of SMP config may be less * trustworthy, simply because the SMP table may have been - * stomped on during early boot. Thankfully the bootloaders - * now honour the EBDA. + * stomped on during early boot. These loaders are buggy and + * should be fixed. + * + * MP1.4 SPEC states to only scan first 1K of 4K EBDA. */ - address = *(unsigned short *)phys_to_virt(0x40E); - address <<= 4; - smp_scan_config(address, 0x1000); + address = get_bios_ebda(); + if (address) + smp_scan_config(address, 0x400); } -#else - -/* - * The Visual Workstation is Intel MP compliant in the hardware - * sense, but it doesn't have a BIOS(-configuration table). - * No problem for Linux. - */ -void __init find_visws_smp(void) -{ - smp_found_config = 1; - - phys_cpu_present_map |= 2; /* or in id 1 */ - apic_version[1] |= 0x10; /* integrated APIC */ - apic_version[0] |= 0x10; - - mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; -} - -#endif - -/* - * - Intel MP Configuration Table - * - or SGI Visual Workstation configuration - */ -void __init find_smp_config (void) -{ -#ifdef CONFIG_X86_LOCAL_APIC - find_intel_smp(); -#endif -#ifdef CONFIG_VISWS - find_visws_smp(); -#endif -} - - /* -------------------------------------------------------------------------- ACPI-based MP Configuration -------------------------------------------------------------------------- */ @@ -987,7 +836,7 @@ void __init mp_register_lapic ( struct mpc_config_processor processor; int boot_cpu = 0; - if (id >= MAX_APICS) { + if (MAX_APICS - id <= 0) { printk(KERN_WARNING "Processor #%d invalid (max %d)\n", id, MAX_APICS); return; @@ -998,14 +847,7 @@ void __init mp_register_lapic ( processor.mpc_type = MP_PROCESSOR; processor.mpc_apicid = id; - - /* - * mp_register_lapic_address() which is called before the - * current function does the fixmap of FIX_APIC_BASE. - * Read in the correct APIC version from there - */ - processor.mpc_apicver = apic_read(APIC_LVR); - + processor.mpc_apicver = GET_APIC_VERSION(apic_read(APIC_LVR)); processor.mpc_cpuflag = (enabled ? CPU_ENABLED : 0); processor.mpc_cpuflag |= (boot_cpu ? CPU_BOOTPROCESSOR : 0); processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) | @@ -1017,32 +859,32 @@ void __init mp_register_lapic ( MP_processor_info(&processor); } -#if defined(CONFIG_X86_IO_APIC) /*&& defined(CONFIG_ACPI_INTERPRETER)*/ +#if defined(CONFIG_X86_IO_APIC) && (defined(CONFIG_ACPI_INTERPRETER) || defined(CONFIG_ACPI_BOOT)) #define MP_ISA_BUS 0 #define MP_MAX_IOAPIC_PIN 127 struct mp_ioapic_routing { int apic_id; - int irq_start; - int irq_end; + int gsi_base; + int gsi_end; u32 pin_programmed[4]; } mp_ioapic_routing[MAX_IO_APICS]; -static int __init mp_find_ioapic ( - int irq) +static int mp_find_ioapic ( + int gsi) { int i = 0; - /* Find the IOAPIC that manages this IRQ. */ + /* Find the IOAPIC that manages this GSI. */ for (i = 0; i < nr_ioapics; i++) { - if ((irq >= mp_ioapic_routing[i].irq_start) - && (irq <= mp_ioapic_routing[i].irq_end)) + if ((gsi >= mp_ioapic_routing[i].gsi_base) + && (gsi <= mp_ioapic_routing[i].gsi_end)) return i; } - printk(KERN_ERR "ERROR: Unable to locate IOAPIC for IRQ %d\n", irq); + printk(KERN_ERR "ERROR: Unable to locate IOAPIC for GSI %d\n", gsi); return -1; } @@ -1051,7 +893,7 @@ static int __init mp_find_ioapic ( void __init mp_register_ioapic ( u8 id, u32 address, - u32 irq_base) + u32 gsi_base) { int idx = 0; @@ -1077,19 +919,19 @@ void __init mp_register_ioapic ( mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx); /* - * Build basic IRQ lookup table to facilitate irq->io_apic lookups - * and to prevent reprogramming of IOAPIC pins (PCI IRQs). + * Build basic GSI lookup table to facilitate gsi->io_apic lookups + * and to prevent reprogramming of IOAPIC pins (PCI GSIs). */ mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].mpc_apicid; - mp_ioapic_routing[idx].irq_start = irq_base; - mp_ioapic_routing[idx].irq_end = irq_base + + mp_ioapic_routing[idx].gsi_base = gsi_base; + mp_ioapic_routing[idx].gsi_end = gsi_base + io_apic_get_redir_entries(idx); printk("IOAPIC[%d]: apic_id %d, version %d, address 0x%x, " - "IRQ %d-%d\n", idx, mp_ioapics[idx].mpc_apicid, + "GSI %d-%d\n", idx, mp_ioapics[idx].mpc_apicid, mp_ioapics[idx].mpc_apicver, mp_ioapics[idx].mpc_apicaddr, - mp_ioapic_routing[idx].irq_start, - mp_ioapic_routing[idx].irq_end); + mp_ioapic_routing[idx].gsi_base, + mp_ioapic_routing[idx].gsi_end); return; } @@ -1099,21 +941,19 @@ void __init mp_override_legacy_irq ( u8 bus_irq, u8 polarity, u8 trigger, - u32 global_irq) + u32 gsi) { struct mpc_config_intsrc intsrc; - int i = 0; - int found = 0; int ioapic = -1; int pin = -1; /* - * Convert 'global_irq' to 'ioapic.pin'. + * Convert 'gsi' to 'ioapic.pin'. */ - ioapic = mp_find_ioapic(global_irq); + ioapic = mp_find_ioapic(gsi); if (ioapic < 0) return; - pin = global_irq - mp_ioapic_routing[ioapic].irq_start; + pin = gsi - mp_ioapic_routing[ioapic].gsi_base; /* * TBD: This check is for faulty timer entries, where the override @@ -1136,23 +976,9 @@ void __init mp_override_legacy_irq ( (intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus, intsrc.mpc_srcbusirq, intsrc.mpc_dstapic, intsrc.mpc_dstirq); - /* - * If an existing [IOAPIC.PIN -> IRQ] routing entry exists we override it. - * Otherwise create a new entry (e.g. global_irq == 2). - */ - for (i = 0; i < mp_irq_entries; i++) { - if ((mp_irqs[i].mpc_srcbus == intsrc.mpc_srcbus) - && (mp_irqs[i].mpc_srcbusirq == intsrc.mpc_srcbusirq)) { - mp_irqs[i] = intsrc; - found = 1; - break; - } - } - if (!found) { - mp_irqs[mp_irq_entries] = intsrc; - if (++mp_irq_entries == MAX_IRQ_SOURCES) - panic("Max # of irq sources exceeded!\n"); - } + mp_irqs[mp_irq_entries] = intsrc; + if (++mp_irq_entries == MAX_IRQ_SOURCES) + panic("Max # of irq sources exceeded!\n"); return; } @@ -1160,35 +986,22 @@ void __init mp_override_legacy_irq ( void __init mp_config_acpi_legacy_irqs (void) { + struct mpc_config_intsrc intsrc; int i = 0; int ioapic = -1; - /* - * Initialize mp_irqs for IRQ configuration. - */ - unsigned char *bus_data; - int count; - - count = (MAX_MP_BUSSES * sizeof(int)) * 4; - count += (MAX_IRQ_SOURCES * sizeof(int)) * 4; - bus_data = (void *)alloc_xenheap_pages(get_order(count)); - if (!bus_data) { - panic("Fatal: can't allocate bus memory for ACPI legacy IRQ!"); - } - mp_bus_id_to_type = (int *)&bus_data[0]; - mp_bus_id_to_node = (int *)&bus_data[(MAX_MP_BUSSES * sizeof(int))]; - mp_bus_id_to_local = (int *)&bus_data[(MAX_MP_BUSSES * sizeof(int)) * 2]; - mp_bus_id_to_pci_bus = (int *)&bus_data[(MAX_MP_BUSSES * sizeof(int)) * 3]; - mp_irqs = (struct mpc_config_intsrc *)&bus_data[(MAX_MP_BUSSES * sizeof(int)) * 4]; - for (i = 0; i < MAX_MP_BUSSES; ++i) - mp_bus_id_to_pci_bus[i] = -1; - /* * Fabricate the legacy ISA bus (bus #31). */ mp_bus_id_to_type[MP_ISA_BUS] = MP_BUS_ISA; Dprintk("Bus #%d is ISA\n", MP_ISA_BUS); + /* + * ES7000 has no legacy identity mappings + */ + if (es7000_plat) + return; + /* * Locate the IOAPIC that manages the ISA IRQs (0-15). */ @@ -1196,118 +1009,101 @@ void __init mp_config_acpi_legacy_irqs (void) if (ioapic < 0) return; + intsrc.mpc_type = MP_INTSRC; + intsrc.mpc_irqflag = 0; /* Conforming */ + intsrc.mpc_srcbus = MP_ISA_BUS; + intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid; + /* - * Use the default configuration for the IRQs 0-15. These may be + * Use the default configuration for the IRQs 0-15. Unless * overriden by (MADT) interrupt source override entries. */ for (i = 0; i < 16; i++) { + int idx; - if (i == 2) - continue; /* Don't connect IRQ2 */ + for (idx = 0; idx < mp_irq_entries; idx++) { + struct mpc_config_intsrc *irq = mp_irqs + idx; - mp_irqs[mp_irq_entries].mpc_type = MP_INTSRC; - mp_irqs[mp_irq_entries].mpc_irqflag = 0; /* Conforming */ - mp_irqs[mp_irq_entries].mpc_srcbus = MP_ISA_BUS; - mp_irqs[mp_irq_entries].mpc_dstapic = mp_ioapics[ioapic].mpc_apicid; - mp_irqs[mp_irq_entries].mpc_irqtype = mp_INT; - mp_irqs[mp_irq_entries].mpc_srcbusirq = i; /* Identity mapped */ - mp_irqs[mp_irq_entries].mpc_dstirq = i; + /* Do we already have a mapping for this ISA IRQ? */ + if (irq->mpc_srcbus == MP_ISA_BUS && irq->mpc_srcbusirq == i) + break; + + /* Do we already have a mapping for this IOAPIC pin */ + if ((irq->mpc_dstapic == intsrc.mpc_dstapic) && + (irq->mpc_dstirq == i)) + break; + } + + if (idx != mp_irq_entries) { + printk(KERN_DEBUG "ACPI: IRQ%d used by override.\n", i); + continue; /* IRQ already used */ + } + + intsrc.mpc_irqtype = mp_INT; + intsrc.mpc_srcbusirq = i; /* Identity mapped */ + intsrc.mpc_dstirq = i; Dprintk("Int: type %d, pol %d, trig %d, bus %d, irq %d, " - "%d-%d\n", - mp_irqs[mp_irq_entries].mpc_irqtype, - mp_irqs[mp_irq_entries].mpc_irqflag & 3, - (mp_irqs[mp_irq_entries].mpc_irqflag >> 2) & 3, - mp_irqs[mp_irq_entries].mpc_srcbus, - mp_irqs[mp_irq_entries].mpc_srcbusirq, - mp_irqs[mp_irq_entries].mpc_dstapic, - mp_irqs[mp_irq_entries].mpc_dstirq); + "%d-%d\n", intsrc.mpc_irqtype, intsrc.mpc_irqflag & 3, + (intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus, + intsrc.mpc_srcbusirq, intsrc.mpc_dstapic, + intsrc.mpc_dstirq); + mp_irqs[mp_irq_entries] = intsrc; if (++mp_irq_entries == MAX_IRQ_SOURCES) panic("Max # of irq sources exceeded!\n"); } } -#ifdef CONFIG_ACPI_PCI - -void __init mp_parse_prt (void) +int mp_register_gsi (u32 gsi, int edge_level, int active_high_low) { - struct acpi_prt_entry *entry = NULL; int ioapic = -1; int ioapic_pin = 0; - int irq = 0; int idx, bit = 0; - int edge_level = 0; - int active_high_low = 0; - /* - * Parsing through the PCI Interrupt Routing Table (PRT) and program - * routing for all entries. - */ - list_for_each_entry(entry, &acpi_prt.entries, node) { - /* Need to get irq for dynamic entry */ - if (entry->link.handle) { - irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, &edge_level, &active_high_low); - if (!irq) - continue; - } - else { - /* Hardwired IRQ. Assume PCI standard settings */ - irq = entry->link.index; - edge_level = 1; - active_high_low = 1; - } +#ifdef CONFIG_ACPI_BUS + /* Don't set up the ACPI SCI because it's already set up */ + if (acpi_fadt.sci_int == gsi) + return gsi; +#endif - /* Don't set up the ACPI SCI because it's already set up */ - if (acpi_fadt.sci_int == irq) { - entry->irq = irq; /*we still need to set entry's irq*/ - continue; - } - - ioapic = mp_find_ioapic(irq); - if (ioapic < 0) - continue; - ioapic_pin = irq - mp_ioapic_routing[ioapic].irq_start; - - /* - * Avoid pin reprogramming. PRTs typically include entries - * with redundant pin->irq mappings (but unique PCI devices); - * we only only program the IOAPIC on the first. - */ - bit = ioapic_pin % 32; - idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32); - if (idx > 3) { - printk(KERN_ERR "Invalid reference to IOAPIC pin " - "%d-%d\n", mp_ioapic_routing[ioapic].apic_id, - ioapic_pin); - continue; - } - if ((1<irq = irq; - continue; - } + ioapic = mp_find_ioapic(gsi); + if (ioapic < 0) { + printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi); + return gsi; + } - mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<irq = irq; + if (ioapic_renumber_irq) + gsi = ioapic_renumber_irq(ioapic, gsi); - printk(KERN_DEBUG "%02x:%02x:%02x[%c] -> %d-%d -> IRQ %d\n", - entry->id.segment, entry->id.bus, - entry->id.device, ('A' + entry->pin), - mp_ioapic_routing[ioapic].apic_id, ioapic_pin, - entry->irq); + /* + * Avoid pin reprogramming. PRTs typically include entries + * with redundant pin->gsi mappings (but unique PCI devices); + * we only program the IOAPIC on the first. + */ + bit = ioapic_pin % 32; + idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32); + if (idx > 3) { + printk(KERN_ERR "Invalid reference to IOAPIC pin " + "%d-%d\n", mp_ioapic_routing[ioapic].apic_id, + ioapic_pin); + return gsi; + } + if ((1< #include #include +#include #include #include #include diff --git a/xen/arch/x86/nmi.c b/xen/arch/x86/nmi.c index ee798f9a36..afdf8051bb 100644 --- a/xen/arch/x86/nmi.c +++ b/xen/arch/x86/nmi.c @@ -86,24 +86,20 @@ extern int logical_proc_id[]; int __init check_nmi_watchdog (void) { unsigned int prev_nmi_count[NR_CPUS]; - int j, cpu; + int cpu; if ( !nmi_watchdog ) return 0; printk("Testing NMI watchdog --- "); - for ( j = 0; j < smp_num_cpus; j++ ) - { - cpu = cpu_logical_map(j); + for ( cpu = 0; cpu < smp_num_cpus; cpu++ ) prev_nmi_count[cpu] = nmi_count(cpu); - } __sti(); mdelay((10*1000)/nmi_hz); /* wait 10 ticks */ - for ( j = 0; j < smp_num_cpus; j++ ) + for ( cpu = 0; cpu < smp_num_cpus; cpu++ ) { - cpu = cpu_logical_map(j); if ( nmi_count(cpu) - prev_nmi_count[cpu] <= 5 ) printk("CPU#%d stuck. ", cpu); else diff --git a/xen/arch/x86/physdev.c b/xen/arch/x86/physdev.c index 66e0ed1251..5de96ec96d 100644 --- a/xen/arch/x86/physdev.c +++ b/xen/arch/x86/physdev.c @@ -10,8 +10,6 @@ #include #include -extern void (*interrupt[])(void); - extern int ioapic_guest_read(int apicid, int address, u32 *pval); extern int ioapic_guest_write(int apicid, int address, u32 pval); diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c index 981a36d97d..7a3abe9913 100644 --- a/xen/arch/x86/smpboot.c +++ b/xen/arch/x86/smpboot.c @@ -48,8 +48,8 @@ #include #include #include - -#ifdef CONFIG_SMP +#include +#include /* Cconfigured maximum number of CPUs to activate. We name the parameter "maxcpus" rather than max_cpus to be compatible with Linux */ @@ -63,10 +63,10 @@ int smp_num_cpus = 1; int ht_per_core = 1; /* Bitmask of currently online CPUs */ -unsigned long cpu_online_map; +cpumask_t cpu_online_map; -static volatile unsigned long cpu_callin_map; -static volatile unsigned long cpu_callout_map; +cpumask_t cpu_callin_map; +cpumask_t cpu_callout_map; /* Per CPU bogomips and other parameters */ struct cpuinfo_x86 cpu_data[NR_CPUS]; @@ -800,7 +800,8 @@ void __init smp_boot_cpus(void) if (!smp_found_config) { printk("SMP motherboard not detected.\n"); io_apic_irqs = 0; - cpu_online_map = phys_cpu_present_map = 1; + phys_cpu_present_map = physid_mask_of_physid(0); + cpu_online_map = 1; smp_num_cpus = 1; if (APIC_init_uniprocessor()) printk("Local APIC not detected." @@ -815,7 +816,7 @@ void __init smp_boot_cpus(void) if (!test_bit(boot_cpu_physical_apicid, &phys_cpu_present_map)) { printk("weird, boot CPU (#%d) not listed by the BIOS.\n", boot_cpu_physical_apicid); - phys_cpu_present_map |= (1 << hard_smp_processor_id()); + physid_set(hard_smp_processor_id(), phys_cpu_present_map); } /* @@ -827,7 +828,8 @@ void __init smp_boot_cpus(void) boot_cpu_physical_apicid); printk("... forcing use of dummy APIC emulation. (tell your hw vendor)\n"); io_apic_irqs = 0; - cpu_online_map = phys_cpu_present_map = 1; + phys_cpu_present_map = physid_mask_of_physid(0); + cpu_online_map = 1; smp_num_cpus = 1; goto smp_done; } @@ -841,7 +843,8 @@ void __init smp_boot_cpus(void) smp_found_config = 0; printk("SMP mode deactivated, forcing use of dummy APIC emulation.\n"); io_apic_irqs = 0; - cpu_online_map = phys_cpu_present_map = 1; + phys_cpu_present_map = physid_mask_of_physid(0); + cpu_online_map = 1; smp_num_cpus = 1; goto smp_done; } @@ -875,7 +878,7 @@ void __init smp_boot_cpus(void) if (opt_noht && (apicid & (ht_per_core - 1))) continue; - if (!(phys_cpu_present_map & (1 << bit))) + if (!check_apicid_present(bit)) continue; if ((max_cpus >= 0) && (max_cpus <= cpucount+1)) continue; @@ -886,7 +889,7 @@ void __init smp_boot_cpus(void) * Make sure we unmap all failed CPUs */ if ((boot_apicid_to_cpu(apicid) == -1) && - (phys_cpu_present_map & (1 << bit))) + (!check_apicid_present(bit))) printk("CPU #%d not responding - cannot use it.\n", apicid); } @@ -923,7 +926,10 @@ void __init smp_boot_cpus(void) if ( nr_ioapics ) setup_IO_APIC(); /* Set up all local APIC timers in the system. */ - setup_APIC_clocks(); + { + extern void setup_APIC_clocks(void); + setup_APIC_clocks(); + } /* Synchronize the TSC with the AP(s). */ if ( cpucount ) synchronize_tsc_bp(); @@ -932,8 +938,6 @@ void __init smp_boot_cpus(void) ; } -#endif /* CONFIG_SMP */ - /* * Local variables: * mode: C diff --git a/xen/arch/x86/x86_32/asm-offsets.c b/xen/arch/x86/x86_32/asm-offsets.c index 7015b2a861..b440b0501e 100644 --- a/xen/arch/x86/x86_32/asm-offsets.c +++ b/xen/arch/x86/x86_32/asm-offsets.c @@ -90,7 +90,7 @@ void __dummy__(void) OFFSET(MULTICALL_result, multicall_entry_t, args[5]); BLANK(); - DEFINE(FIXMAP_apic_base, fix_to_virt(FIX_APIC_BASE)); + DEFINE(FIXMAP_apic_base, __fix_to_virt(FIX_APIC_BASE)); BLANK(); DEFINE(IRQSTAT_shift, LOG_2(sizeof(irq_cpustat_t))); diff --git a/xen/arch/x86/x86_32/mm.c b/xen/arch/x86/x86_32/mm.c index 045d904c21..e88195a8e1 100644 --- a/xen/arch/x86/x86_32/mm.c +++ b/xen/arch/x86/x86_32/mm.c @@ -83,7 +83,7 @@ void __set_fixmap( { if ( unlikely(idx >= __end_of_fixed_addresses) ) BUG(); - map_pages(idle_pg_table, fix_to_virt(idx), p, PAGE_SIZE, flags); + map_pages(idle_pg_table, __fix_to_virt(idx), p, PAGE_SIZE, flags); } diff --git a/xen/arch/x86/x86_32/traps.c b/xen/arch/x86/x86_32/traps.c index bd14acde01..d3453802b9 100644 --- a/xen/arch/x86/x86_32/traps.c +++ b/xen/arch/x86/x86_32/traps.c @@ -273,12 +273,8 @@ long set_fast_trap(struct exec_domain *p, int idx) return 0; } - /* - * We only fast-trap vectors 0x20-0x2f, and vector 0x80. - * The former range is used by Windows and MS-DOS. - * Vector 0x80 is used by Linux and the BSD variants. - */ - if ( (idx != 0x80) && ((idx < 0x20) || (idx > 0x2f)) ) + /* We only fast-trap vector 0x80 (used by Linux and the BSD variants). */ + if ( idx != 0x80 ) return -1; ti = &p->arch.guest_context.trap_ctxt[idx]; diff --git a/xen/arch/x86/x86_64/mm.c b/xen/arch/x86/x86_64/mm.c index a1db5acd05..3becac2024 100644 --- a/xen/arch/x86/x86_64/mm.c +++ b/xen/arch/x86/x86_64/mm.c @@ -125,7 +125,7 @@ void __set_fixmap( { if ( unlikely(idx >= __end_of_fixed_addresses) ) BUG(); - map_pages(idle_pg_table, fix_to_virt(idx), p, PAGE_SIZE, flags); + map_pages(idle_pg_table, __fix_to_virt(idx), p, PAGE_SIZE, flags); } diff --git a/xen/common/bitmap.c b/xen/common/bitmap.c new file mode 100644 index 0000000000..d931eca83c --- /dev/null +++ b/xen/common/bitmap.c @@ -0,0 +1,365 @@ +/* + * lib/bitmap.c + * Helper functions for bitmap.h. + * + * This source code is licensed under the GNU General Public License, + * Version 2. See the file COPYING for more details. + */ +#include +#include +#include +#include +#include +#include + +/* + * bitmaps provide an array of bits, implemented using an an + * array of unsigned longs. The number of valid bits in a + * given bitmap does _not_ need to be an exact multiple of + * BITS_PER_LONG. + * + * The possible unused bits in the last, partially used word + * of a bitmap are 'don't care'. The implementation makes + * no particular effort to keep them zero. It ensures that + * their value will not affect the results of any operation. + * The bitmap operations that return Boolean (bitmap_empty, + * for example) or scalar (bitmap_weight, for example) results + * carefully filter out these unused bits from impacting their + * results. + * + * These operations actually hold to a slightly stronger rule: + * if you don't input any bitmaps to these ops that have some + * unused bits set, then they won't output any set unused bits + * in output bitmaps. + * + * The byte ordering of bitmaps is more natural on little + * endian architectures. See the big-endian headers + * include/asm-ppc64/bitops.h and include/asm-s390/bitops.h + * for the best explanations of this ordering. + */ + +int __bitmap_empty(const unsigned long *bitmap, int bits) +{ + int k, lim = bits/BITS_PER_LONG; + for (k = 0; k < lim; ++k) + if (bitmap[k]) + return 0; + + if (bits % BITS_PER_LONG) + if (bitmap[k] & BITMAP_LAST_WORD_MASK(bits)) + return 0; + + return 1; +} +EXPORT_SYMBOL(__bitmap_empty); + +int __bitmap_full(const unsigned long *bitmap, int bits) +{ + int k, lim = bits/BITS_PER_LONG; + for (k = 0; k < lim; ++k) + if (~bitmap[k]) + return 0; + + if (bits % BITS_PER_LONG) + if (~bitmap[k] & BITMAP_LAST_WORD_MASK(bits)) + return 0; + + return 1; +} +EXPORT_SYMBOL(__bitmap_full); + +int __bitmap_equal(const unsigned long *bitmap1, + const unsigned long *bitmap2, int bits) +{ + int k, lim = bits/BITS_PER_LONG; + for (k = 0; k < lim; ++k) + if (bitmap1[k] != bitmap2[k]) + return 0; + + if (bits % BITS_PER_LONG) + if ((bitmap1[k] ^ bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits)) + return 0; + + return 1; +} +EXPORT_SYMBOL(__bitmap_equal); + +void __bitmap_complement(unsigned long *dst, const unsigned long *src, int bits) +{ + int k, lim = bits/BITS_PER_LONG; + for (k = 0; k < lim; ++k) + dst[k] = ~src[k]; + + if (bits % BITS_PER_LONG) + dst[k] = ~src[k] & BITMAP_LAST_WORD_MASK(bits); +} +EXPORT_SYMBOL(__bitmap_complement); + +/* + * __bitmap_shift_right - logical right shift of the bits in a bitmap + * @dst - destination bitmap + * @src - source bitmap + * @nbits - shift by this many bits + * @bits - bitmap size, in bits + * + * Shifting right (dividing) means moving bits in the MS -> LS bit + * direction. Zeros are fed into the vacated MS positions and the + * LS bits shifted off the bottom are lost. + */ +void __bitmap_shift_right(unsigned long *dst, + const unsigned long *src, int shift, int bits) +{ + int k, lim = BITS_TO_LONGS(bits), left = bits % BITS_PER_LONG; + int off = shift/BITS_PER_LONG, rem = shift % BITS_PER_LONG; + unsigned long mask = (1UL << left) - 1; + for (k = 0; off + k < lim; ++k) { + unsigned long upper, lower; + + /* + * If shift is not word aligned, take lower rem bits of + * word above and make them the top rem bits of result. + */ + if (!rem || off + k + 1 >= lim) + upper = 0; + else { + upper = src[off + k + 1]; + if (off + k + 1 == lim - 1 && left) + upper &= mask; + } + lower = src[off + k]; + if (left && off + k == lim - 1) + lower &= mask; + dst[k] = upper << (BITS_PER_LONG - rem) | lower >> rem; + if (left && k == lim - 1) + dst[k] &= mask; + } + if (off) + memset(&dst[lim - off], 0, off*sizeof(unsigned long)); +} +EXPORT_SYMBOL(__bitmap_shift_right); + + +/* + * __bitmap_shift_left - logical left shift of the bits in a bitmap + * @dst - destination bitmap + * @src - source bitmap + * @nbits - shift by this many bits + * @bits - bitmap size, in bits + * + * Shifting left (multiplying) means moving bits in the LS -> MS + * direction. Zeros are fed into the vacated LS bit positions + * and those MS bits shifted off the top are lost. + */ + +void __bitmap_shift_left(unsigned long *dst, + const unsigned long *src, int shift, int bits) +{ + int k, lim = BITS_TO_LONGS(bits), left = bits % BITS_PER_LONG; + int off = shift/BITS_PER_LONG, rem = shift % BITS_PER_LONG; + for (k = lim - off - 1; k >= 0; --k) { + unsigned long upper, lower; + + /* + * If shift is not word aligned, take upper rem bits of + * word below and make them the bottom rem bits of result. + */ + if (rem && k > 0) + lower = src[k - 1]; + else + lower = 0; + upper = src[k]; + if (left && k == lim - 1) + upper &= (1UL << left) - 1; + dst[k + off] = lower >> (BITS_PER_LONG - rem) | upper << rem; + if (left && k + off == lim - 1) + dst[k + off] &= (1UL << left) - 1; + } + if (off) + memset(dst, 0, off*sizeof(unsigned long)); +} +EXPORT_SYMBOL(__bitmap_shift_left); + +void __bitmap_and(unsigned long *dst, const unsigned long *bitmap1, + const unsigned long *bitmap2, int bits) +{ + int k; + int nr = BITS_TO_LONGS(bits); + + for (k = 0; k < nr; k++) + dst[k] = bitmap1[k] & bitmap2[k]; +} +EXPORT_SYMBOL(__bitmap_and); + +void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1, + const unsigned long *bitmap2, int bits) +{ + int k; + int nr = BITS_TO_LONGS(bits); + + for (k = 0; k < nr; k++) + dst[k] = bitmap1[k] | bitmap2[k]; +} +EXPORT_SYMBOL(__bitmap_or); + +void __bitmap_xor(unsigned long *dst, const unsigned long *bitmap1, + const unsigned long *bitmap2, int bits) +{ + int k; + int nr = BITS_TO_LONGS(bits); + + for (k = 0; k < nr; k++) + dst[k] = bitmap1[k] ^ bitmap2[k]; +} +EXPORT_SYMBOL(__bitmap_xor); + +void __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1, + const unsigned long *bitmap2, int bits) +{ + int k; + int nr = BITS_TO_LONGS(bits); + + for (k = 0; k < nr; k++) + dst[k] = bitmap1[k] & ~bitmap2[k]; +} +EXPORT_SYMBOL(__bitmap_andnot); + +int __bitmap_intersects(const unsigned long *bitmap1, + const unsigned long *bitmap2, int bits) +{ + int k, lim = bits/BITS_PER_LONG; + for (k = 0; k < lim; ++k) + if (bitmap1[k] & bitmap2[k]) + return 1; + + if (bits % BITS_PER_LONG) + if ((bitmap1[k] & bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits)) + return 1; + return 0; +} +EXPORT_SYMBOL(__bitmap_intersects); + +int __bitmap_subset(const unsigned long *bitmap1, + const unsigned long *bitmap2, int bits) +{ + int k, lim = bits/BITS_PER_LONG; + for (k = 0; k < lim; ++k) + if (bitmap1[k] & ~bitmap2[k]) + return 0; + + if (bits % BITS_PER_LONG) + if ((bitmap1[k] & ~bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits)) + return 0; + return 1; +} +EXPORT_SYMBOL(__bitmap_subset); + +#if BITS_PER_LONG == 32 +int __bitmap_weight(const unsigned long *bitmap, int bits) +{ + int k, w = 0, lim = bits/BITS_PER_LONG; + + for (k = 0; k < lim; k++) + w += hweight32(bitmap[k]); + + if (bits % BITS_PER_LONG) + w += hweight32(bitmap[k] & BITMAP_LAST_WORD_MASK(bits)); + + return w; +} +#else +int __bitmap_weight(const unsigned long *bitmap, int bits) +{ + int k, w = 0, lim = bits/BITS_PER_LONG; + + for (k = 0; k < lim; k++) + w += hweight64(bitmap[k]); + + if (bits % BITS_PER_LONG) + w += hweight64(bitmap[k] & BITMAP_LAST_WORD_MASK(bits)); + + return w; +} +#endif +EXPORT_SYMBOL(__bitmap_weight); + +/** + * bitmap_find_free_region - find a contiguous aligned mem region + * @bitmap: an array of unsigned longs corresponding to the bitmap + * @bits: number of bits in the bitmap + * @order: region size to find (size is actually 1< BITS_PER_LONG) + return -EINVAL; + + /* make a mask of the order */ + mask = (1ul << (pages - 1)); + mask += mask - 1; + + /* run up the bitmap pages bits at a time */ + for (i = 0; i < bits; i += pages) { + int index = i/BITS_PER_LONG; + int offset = i - (index * BITS_PER_LONG); + if((bitmap[index] & (mask << offset)) == 0) { + /* set region in bimap */ + bitmap[index] |= (mask << offset); + return i; + } + } + return -ENOMEM; +} +EXPORT_SYMBOL(bitmap_find_free_region); + +/** + * bitmap_release_region - release allocated bitmap region + * @bitmap: a pointer to the bitmap + * @pos: the beginning of the region + * @order: the order of the bits to release (number is 1< BITS_PER_LONG. The + * algorithm would be a simple look for multiple zeros in the + * array, but there's no driver today that needs this. If you + * trip this BUG(), you get to code it... */ + BUG_ON(pages > BITS_PER_LONG); + mask += mask - 1; + if (bitmap[index] & (mask << offset)) + return -EBUSY; + bitmap[index] |= (mask << offset); + return 0; +} +EXPORT_SYMBOL(bitmap_allocate_region); diff --git a/xen/common/xmalloc.c b/xen/common/xmalloc.c index bb90cc392d..de4831e18c 100644 --- a/xen/common/xmalloc.c +++ b/xen/common/xmalloc.c @@ -42,7 +42,7 @@ struct xmalloc_hdr /* Total including this hdr. */ size_t size; struct list_head freelist; -} __attribute__((__aligned__(SMP_CACHE_BYTES))); +} __cacheline_aligned; static void maybe_split(struct xmalloc_hdr *hdr, size_t size, size_t block) { diff --git a/xen/drivers/acpi/tables.c b/xen/drivers/acpi/tables.c index 64a05061a6..1c718efc88 100644 --- a/xen/drivers/acpi/tables.c +++ b/xen/drivers/acpi/tables.c @@ -58,6 +58,7 @@ static char *acpi_table_signatures[ACPI_TABLE_COUNT] = { [ACPI_SSDT] = "SSDT", [ACPI_SPMI] = "SPMI", [ACPI_HPET] = "HPET", + [ACPI_MCFG] = "MCFG", }; static char *mps_inti_flags_polarity[] = { "dfl", "high", "res", "low" }; @@ -100,7 +101,7 @@ acpi_table_print ( else name = header->signature; - printk(KERN_INFO PREFIX "%.4s (v%3.3d %6.6s %8.8s 0x%08x %.4s 0x%08x) @ 0x%p\n", + printk(KERN_DEBUG PREFIX "%.4s (v%3.3d %6.6s %8.8s 0x%08x %.4s 0x%08x) @ 0x%p\n", name, header->revision, header->oem_id, header->oem_table_id, header->oem_revision, header->asl_compiler_id, header->asl_compiler_revision, @@ -130,7 +131,7 @@ acpi_table_print_madt_entry ( { struct acpi_table_ioapic *p = (struct acpi_table_ioapic*) header; - printk(KERN_INFO PREFIX "IOAPIC (id[0x%02x] address[0x%08x] global_irq_base[0x%x])\n", + printk(KERN_INFO PREFIX "IOAPIC (id[0x%02x] address[0x%08x] gsi_base[%d])\n", p->id, p->address, p->global_irq_base); } break; @@ -184,8 +185,8 @@ acpi_table_print_madt_entry ( { struct acpi_table_iosapic *p = (struct acpi_table_iosapic*) header; - printk(KERN_INFO PREFIX "IOSAPIC (id[0x%x] global_irq_base[0x%x] address[%p])\n", - p->id, p->global_irq_base, (void *) (unsigned long) p->address); + printk(KERN_INFO PREFIX "IOSAPIC (id[0x%x] address[%p] gsi_base[%d])\n", + p->id, (void *) (unsigned long) p->address, p->global_irq_base); } break; @@ -285,7 +286,7 @@ acpi_get_table_header_early ( *header = (void *) __acpi_map_table(fadt->V1_dsdt, sizeof(struct acpi_table_header)); } else - *header = 0; + *header = NULL; if (!*header) { printk(KERN_WARNING PREFIX "Unable to map DSDT\n"); @@ -302,13 +303,14 @@ acpi_table_parse_madt_family ( enum acpi_table_id id, unsigned long madt_size, int entry_id, - acpi_madt_entry_handler handler) + acpi_madt_entry_handler handler, + unsigned int max_entries) { void *madt = NULL; - acpi_table_entry_header *entry = NULL; - unsigned long count = 0; - unsigned long madt_end = 0; - unsigned int i = 0; + acpi_table_entry_header *entry; + unsigned int count = 0; + unsigned long madt_end; + unsigned int i; if (!handler) return -EINVAL; @@ -341,14 +343,20 @@ acpi_table_parse_madt_family ( entry = (acpi_table_entry_header *) ((unsigned long) madt + madt_size); - while (((unsigned long) entry) < madt_end) { - if (entry->type == entry_id) { - count++; - handler(entry); - } + while (((unsigned long) entry) + sizeof(acpi_table_entry_header) < madt_end) { + if (entry->type == entry_id && + (!max_entries || count++ < max_entries)) + if (handler(entry, madt_end)) + return -EINVAL; + entry = (acpi_table_entry_header *) ((unsigned long) entry + entry->length); } + if (max_entries && count > max_entries) { + printk(KERN_WARNING PREFIX "[%s:0x%02x] ignored %i entries of " + "%i found\n", acpi_table_signatures[id], entry_id, + count - max_entries, count); + } return count; } @@ -357,10 +365,11 @@ acpi_table_parse_madt_family ( int __init acpi_table_parse_madt ( enum acpi_madt_entry_id id, - acpi_madt_entry_handler handler) + acpi_madt_entry_handler handler, + unsigned int max_entries) { return acpi_table_parse_madt_family(ACPI_APIC, sizeof(struct acpi_table_madt), - id, handler); + id, handler, max_entries); } @@ -378,8 +387,13 @@ acpi_table_parse ( for (i = 0; i < sdt_count; i++) { if (sdt_entry[i].id != id) continue; - handler(sdt_entry[i].pa, sdt_entry[i].size); count++; + if (count == 1) + handler(sdt_entry[i].pa, sdt_entry[i].size); + + else + printk(KERN_WARNING PREFIX "%d duplicate %s table ignored.\n", + count, acpi_table_signatures[id]); } return count; @@ -543,6 +557,14 @@ acpi_table_get_sdt ( return 0; } +/* + * acpi_table_init() + * + * find RSDP, find and checksum SDT/XSDT. + * checksum all tables, print SDT/XSDT + * + * result: sdt_entry[] is initialized + */ int __init acpi_table_init (void) @@ -565,7 +587,7 @@ acpi_table_init (void) return -ENODEV; } - printk(KERN_INFO PREFIX "RSDP (v%3.3d %6.6s ) @ 0x%p\n", + printk(KERN_DEBUG PREFIX "RSDP (v%3.3d %6.6s ) @ 0x%p\n", rsdp->revision, rsdp->oem_id, (void *) rsdp_phys); if (rsdp->revision < 2) @@ -585,4 +607,3 @@ acpi_table_init (void) return 0; } - diff --git a/xen/include/acpi/acconfig.h b/xen/include/acpi/acconfig.h index 8879c2c830..6701c11b40 100644 --- a/xen/include/acpi/acconfig.h +++ b/xen/include/acpi/acconfig.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2004, R. Byron Moore + * Copyright (C) 2000 - 2005, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -64,11 +64,21 @@ /* Version string */ -#define ACPI_CA_VERSION 0x20040116 +#define ACPI_CA_VERSION 0x20050211 + +/* + * OS name, used for the _OS object. The _OS object is essentially obsolete, + * but there is a large base of ASL/AML code in existing machines that check + * for the string below. The use of this string usually guarantees that + * the ASL will execute down the most tested code path. Also, there is some + * code that will not execute the _OSI method unless _OS matches the string + * below. Therefore, change this string at your own risk. + */ +#define ACPI_OS_NAME "Microsoft Windows NT" /* Maximum objects in the various object caches */ -#define ACPI_MAX_STATE_CACHE_DEPTH 64 /* State objects for stacks */ +#define ACPI_MAX_STATE_CACHE_DEPTH 64 /* State objects */ #define ACPI_MAX_PARSE_CACHE_DEPTH 96 /* Parse tree objects */ #define ACPI_MAX_EXTPARSE_CACHE_DEPTH 64 /* Parse tree objects */ #define ACPI_MAX_OBJECT_CACHE_DEPTH 64 /* Interpreter operand objects */ @@ -89,7 +99,7 @@ /* Version of ACPI supported */ -#define ACPI_CA_SUPPORT_LEVEL 2 +#define ACPI_CA_SUPPORT_LEVEL 3 /* String size constants */ @@ -152,10 +162,11 @@ /* Constants used in searching for the RSDP in low memory */ -#define ACPI_LO_RSDP_WINDOW_BASE 0 /* Physical Address */ -#define ACPI_HI_RSDP_WINDOW_BASE 0xE0000 /* Physical Address */ -#define ACPI_LO_RSDP_WINDOW_SIZE 0x400 -#define ACPI_HI_RSDP_WINDOW_SIZE 0x20000 +#define ACPI_EBDA_PTR_LOCATION 0x0000040E /* Physical Address */ +#define ACPI_EBDA_PTR_LENGTH 2 +#define ACPI_EBDA_WINDOW_SIZE 1024 +#define ACPI_HI_RSDP_WINDOW_BASE 0x000E0000 /* Physical Address */ +#define ACPI_HI_RSDP_WINDOW_SIZE 0x00020000 #define ACPI_RSDP_SCAN_STEP 16 /* Operation regions */ @@ -185,6 +196,10 @@ #define ACPI_SMBUS_BUFFER_SIZE 34 +/* Number of strings associated with the _OSI reserved method */ + +#define ACPI_NUM_OSI_STRINGS 9 + /****************************************************************************** * diff --git a/xen/include/acpi/acexcep.h b/xen/include/acpi/acexcep.h index 9441f5c1a7..53f8b50fac 100644 --- a/xen/include/acpi/acexcep.h +++ b/xen/include/acpi/acexcep.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2004, R. Byron Moore + * Copyright (C) 2000 - 2005, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -95,8 +95,9 @@ #define AE_LOGICAL_ADDRESS (acpi_status) (0x001B | AE_CODE_ENVIRONMENTAL) #define AE_ABORT_METHOD (acpi_status) (0x001C | AE_CODE_ENVIRONMENTAL) #define AE_SAME_HANDLER (acpi_status) (0x001D | AE_CODE_ENVIRONMENTAL) +#define AE_WAKE_ONLY_GPE (acpi_status) (0x001E | AE_CODE_ENVIRONMENTAL) -#define AE_CODE_ENV_MAX 0x001D +#define AE_CODE_ENV_MAX 0x001E /* * Programmer exceptions @@ -165,7 +166,7 @@ #define AE_AML_CIRCULAR_REFERENCE (acpi_status) (0x0020 | AE_CODE_AML) #define AE_AML_BAD_RESOURCE_LENGTH (acpi_status) (0x0021 | AE_CODE_AML) -#define AE_CODE_AML_MAX 0x0020 +#define AE_CODE_AML_MAX 0x0021 /* * Internal exceptions used for control @@ -222,7 +223,8 @@ char const *acpi_gbl_exception_names_env[] = "AE_NO_GLOBAL_LOCK", "AE_LOGICAL_ADDRESS", "AE_ABORT_METHOD", - "AE_SAME_HANDLER" + "AE_SAME_HANDLER", + "AE_WAKE_ONLY_GPE" }; char const *acpi_gbl_exception_names_pgm[] = diff --git a/xen/include/acpi/acglobal.h b/xen/include/acpi/acglobal.h index 9cf587e950..c7f387a972 100644 --- a/xen/include/acpi/acglobal.h +++ b/xen/include/acpi/acglobal.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2004, R. Byron Moore + * Copyright (C) 2000 - 2005, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -46,17 +46,26 @@ /* - * Ensure that the globals are actually defined only once. + * Ensure that the globals are actually defined and initialized only once. * - * The use of these defines allows a single list of globals (here) in order + * The use of these macros allows a single list of globals (here) in order * to simplify maintenance of the code. */ #ifdef DEFINE_ACPI_GLOBALS #define ACPI_EXTERN +#define ACPI_INIT_GLOBAL(a,b) a=b #else #define ACPI_EXTERN extern +#define ACPI_INIT_GLOBAL(a,b) a #endif +/* + * Keep local copies of these FADT-based registers. NOTE: These globals + * are first in this file for alignment reasons on 64-bit systems. + */ +ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1a_enable; +ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1b_enable; + /***************************************************************************** * @@ -74,6 +83,46 @@ extern u32 acpi_dbg_layer; extern u32 acpi_gbl_nesting_level; +/***************************************************************************** + * + * Runtime configuration (static defaults that can be overriden at runtime) + * + ****************************************************************************/ + +/* + * Enable "slack" in the AML interpreter? Default is FALSE, and the + * interpreter strictly follows the ACPI specification. Setting to TRUE + * allows the interpreter to forgive certain bad AML constructs. Currently: + * 1) Allow "implicit return" of last value in a control method + * 2) Allow access beyond end of operation region + * 3) Allow access to uninitialized locals/args (auto-init to integer 0) + * 4) Allow ANY object type to be a source operand for the Store() operator + */ +ACPI_EXTERN u8 ACPI_INIT_GLOBAL (acpi_gbl_enable_interpreter_slack, FALSE); + +/* + * Automatically serialize ALL control methods? Default is FALSE, meaning + * to use the Serialized/not_serialized method flags on a per method basis. + * Only change this if the ASL code is poorly written and cannot handle + * reentrancy even though methods are marked "not_serialized". + */ +ACPI_EXTERN u8 ACPI_INIT_GLOBAL (acpi_gbl_all_methods_serialized, FALSE); + +/* + * Create the predefined _OSI method in the namespace? Default is TRUE + * because ACPI CA is fully compatible with other ACPI implementations. + * Changing this will revert ACPI CA (and machine ASL) to pre-OSI behavior. + */ +ACPI_EXTERN u8 ACPI_INIT_GLOBAL (acpi_gbl_create_osi_method, TRUE); + +/* + * Disable wakeup GPEs during runtime? Default is TRUE because WAKE and + * RUNTIME GPEs should never be shared, and WAKE GPEs should typically only + * be enabled just before going to sleep. + */ +ACPI_EXTERN u8 ACPI_INIT_GLOBAL (acpi_gbl_leave_wake_gpes_disabled, TRUE); + + /***************************************************************************** * * ACPI Table globals @@ -87,7 +136,6 @@ extern u32 acpi_gbl_nesting_level; * * These tables are single-table only; meaning that there can be at most one * of each in the system. Each global points to the actual table. - * */ ACPI_EXTERN u32 acpi_gbl_table_flags; ACPI_EXTERN u32 acpi_gbl_rsdt_table_count; @@ -97,6 +145,11 @@ ACPI_EXTERN FADT_DESCRIPTOR *acpi_gbl_FADT; ACPI_EXTERN struct acpi_table_header *acpi_gbl_DSDT; ACPI_EXTERN FACS_DESCRIPTOR *acpi_gbl_FACS; ACPI_EXTERN struct acpi_common_facs acpi_gbl_common_fACS; +/* + * Since there may be multiple SSDTs and PSDTS, a single pointer is not + * sufficient; Therefore, there isn't one! + */ + /* * Handle both ACPI 1.0 and ACPI 2.0 Integer widths @@ -107,17 +160,6 @@ ACPI_EXTERN u8 acpi_gbl_integer_bit_width; ACPI_EXTERN u8 acpi_gbl_integer_byte_width; ACPI_EXTERN u8 acpi_gbl_integer_nybble_width; -/* Keep local copies of these FADT-based registers */ - -ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1a_enable; -ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1b_enable; - -/* - * Since there may be multiple SSDTs and PSDTS, a single pointer is not - * sufficient; Therefore, there isn't one! - */ - - /* * ACPI Table info arrays */ @@ -142,6 +184,7 @@ ACPI_EXTERN struct acpi_mutex_info acpi_gbl_mutex_info[NUM_MUTEX]; ACPI_EXTERN struct acpi_memory_list acpi_gbl_memory_lists[ACPI_NUM_MEM_LISTS]; ACPI_EXTERN struct acpi_object_notify_handler acpi_gbl_device_notify; ACPI_EXTERN struct acpi_object_notify_handler acpi_gbl_system_notify; +ACPI_EXTERN acpi_exception_handler acpi_gbl_exception_handler; ACPI_EXTERN acpi_init_handler acpi_gbl_init_handler; ACPI_EXTERN struct acpi_walk_state *acpi_gbl_breakpoint_walk; ACPI_EXTERN acpi_handle acpi_gbl_global_lock_semaphore; @@ -161,13 +204,16 @@ ACPI_EXTERN u8 acpi_gbl_step_to_next_call; ACPI_EXTERN u8 acpi_gbl_acpi_hardware_present; ACPI_EXTERN u8 acpi_gbl_global_lock_present; ACPI_EXTERN u8 acpi_gbl_events_initialized; +ACPI_EXTERN u8 acpi_gbl_system_awake_and_running; extern u8 acpi_gbl_shutdown; extern u32 acpi_gbl_startup_flags; extern const u8 acpi_gbl_decode_to8bit[8]; -extern const char *acpi_gbl_db_sleep_states[ACPI_S_STATE_COUNT]; +extern const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT]; +extern const char *acpi_gbl_highest_dstate_names[4]; extern const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES]; extern const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS]; +extern const char *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STRINGS]; /***************************************************************************** @@ -178,7 +224,7 @@ extern const char *acpi_gbl_region_types[ACPI_NUM_P #define NUM_NS_TYPES ACPI_TYPE_INVALID+1 -#if defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY) +#if !defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY) #define NUM_PREDEFINED_NAMES 10 #else #define NUM_PREDEFINED_NAMES 9 @@ -186,6 +232,7 @@ extern const char *acpi_gbl_region_types[ACPI_NUM_P ACPI_EXTERN struct acpi_namespace_node acpi_gbl_root_node_struct; ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_root_node; +ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_fadt_gpe_device; extern const u8 acpi_gbl_ns_properties[NUM_NS_TYPES]; extern const struct acpi_predefined_names acpi_gbl_pre_defined_names [NUM_PREDEFINED_NAMES]; diff --git a/xen/include/acpi/achware.h b/xen/include/acpi/achware.h index cfcff91f6d..28ad1398c1 100644 --- a/xen/include/acpi/achware.h +++ b/xen/include/acpi/achware.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2004, R. Byron Moore + * Copyright (C) 2000 - 2005, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -114,15 +114,7 @@ acpi_hw_clear_acpi_status ( /* GPE support */ acpi_status -acpi_hw_enable_gpe ( - struct acpi_gpe_event_info *gpe_event_info); - -void -acpi_hw_enable_gpe_for_wakeup ( - struct acpi_gpe_event_info *gpe_event_info); - -acpi_status -acpi_hw_disable_gpe ( +acpi_hw_write_gpe_enable_reg ( struct acpi_gpe_event_info *gpe_event_info); acpi_status @@ -130,10 +122,6 @@ acpi_hw_disable_gpe_block ( struct acpi_gpe_xrupt_info *gpe_xrupt_info, struct acpi_gpe_block_info *gpe_block); -void -acpi_hw_disable_gpe_for_wakeup ( - struct acpi_gpe_event_info *gpe_event_info); - acpi_status acpi_hw_clear_gpe ( struct acpi_gpe_event_info *gpe_event_info); @@ -143,22 +131,39 @@ acpi_hw_clear_gpe_block ( struct acpi_gpe_xrupt_info *gpe_xrupt_info, struct acpi_gpe_block_info *gpe_block); +#ifdef ACPI_FUTURE_USAGE acpi_status acpi_hw_get_gpe_status ( struct acpi_gpe_event_info *gpe_event_info, acpi_event_status *event_status); +#endif acpi_status -acpi_hw_disable_non_wakeup_gpes ( - void); +acpi_hw_disable_all_gpes ( + u32 flags); acpi_status -acpi_hw_enable_non_wakeup_gpes ( - void); +acpi_hw_enable_all_runtime_gpes ( + u32 flags); + +acpi_status +acpi_hw_enable_all_wakeup_gpes ( + u32 flags); + +acpi_status +acpi_hw_enable_runtime_gpe_block ( + struct acpi_gpe_xrupt_info *gpe_xrupt_info, + struct acpi_gpe_block_info *gpe_block); + +acpi_status +acpi_hw_enable_wakeup_gpe_block ( + struct acpi_gpe_xrupt_info *gpe_xrupt_info, + struct acpi_gpe_block_info *gpe_block); /* ACPI Timer prototypes */ +#ifdef ACPI_FUTURE_USAGE acpi_status acpi_get_timer_resolution ( u32 *resolution); @@ -172,6 +177,6 @@ acpi_get_timer_duration ( u32 start_ticks, u32 end_ticks, u32 *time_elapsed); - +#endif /* ACPI_FUTURE_USAGE */ #endif /* __ACHWARE_H__ */ diff --git a/xen/include/acpi/aclocal.h b/xen/include/acpi/aclocal.h index 129422eacc..f2b96f6be4 100644 --- a/xen/include/acpi/aclocal.h +++ b/xen/include/acpi/aclocal.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2004, R. Byron Moore + * Copyright (C) 2000 - 2005, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -53,7 +53,7 @@ typedef u32 acpi_mutex_handle; /* Total number of aml opcodes defined */ -#define AML_NUM_OPCODES 0x7E +#define AML_NUM_OPCODES 0x7F /***************************************************************************** @@ -189,8 +189,6 @@ struct acpi_namespace_node u8 type; /* Type associated with this name */ u16 owner_id; union acpi_name_union name; /* ACPI Name, always 4 chars per ACPI spec */ - - union acpi_operand_object *object; /* Pointer to attached ACPI object (optional) */ struct acpi_namespace_node *child; /* First child */ struct acpi_namespace_node *peer; /* Next peer*/ @@ -211,10 +209,8 @@ struct acpi_namespace_node #define ANOBJ_METHOD_LOCAL 0x10 #define ANOBJ_METHOD_NO_RETVAL 0x20 #define ANOBJ_METHOD_SOME_NO_RETVAL 0x40 - #define ANOBJ_IS_BIT_OFFSET 0x80 - /* * ACPI Table Descriptor. One per ACPI table */ @@ -309,16 +305,31 @@ struct acpi_create_field_info * ****************************************************************************/ -/* Information about a GPE, one per each GPE in an array */ +/* Dispatch info for each GPE -- either a method or handler, cannot be both */ -struct acpi_gpe_event_info +struct acpi_handler_info { - struct acpi_namespace_node *method_node; /* Method node for this GPE level */ - acpi_gpe_handler handler; /* Address of handler, if any */ + acpi_event_handler address; /* Address of handler, if any */ void *context; /* Context to be passed to handler */ + struct acpi_namespace_node *method_node; /* Method node for this GPE level (saved) */ +}; + +union acpi_gpe_dispatch_info +{ + struct acpi_namespace_node *method_node; /* Method node for this GPE level */ + struct acpi_handler_info *handler; +}; + +/* + * Information about a GPE, one per each GPE in an array. + * NOTE: Important to keep this struct as small as possible. + */ +struct acpi_gpe_event_info +{ + union acpi_gpe_dispatch_info dispatch; /* Either Method or Handler */ struct acpi_gpe_register_info *register_info; /* Backpointer to register info */ - u8 flags; /* Level or Edge */ - u8 bit_mask; /* This GPE within the register */ + u8 flags; /* Misc info about this GPE */ + u8 register_bit; /* This GPE bit within the register */ }; /* Information about a GPE register pair, one per each status/enable pair in an array */ @@ -327,9 +338,8 @@ struct acpi_gpe_register_info { struct acpi_generic_address status_address; /* Address of status reg */ struct acpi_generic_address enable_address; /* Address of enable reg */ - u8 status; /* Current value of status reg */ - u8 enable; /* Current value of enable reg */ - u8 wake_enable; /* Mask of bits to keep enabled when sleeping */ + u8 enable_for_wake; /* GPEs to keep enabled when sleeping */ + u8 enable_for_run; /* GPEs to keep enabled when running */ u8 base_gpe_number; /* Base GPE number for this register */ }; @@ -339,6 +349,7 @@ struct acpi_gpe_register_info */ struct acpi_gpe_block_info { + struct acpi_namespace_node *node; struct acpi_gpe_block_info *previous; struct acpi_gpe_block_info *next; struct acpi_gpe_xrupt_info *xrupt_block; /* Backpointer to interrupt block */ @@ -360,6 +371,13 @@ struct acpi_gpe_xrupt_info }; +struct acpi_gpe_walk_info +{ + struct acpi_namespace_node *gpe_device; + struct acpi_gpe_block_info *gpe_block; +}; + + typedef acpi_status (*ACPI_GPE_CALLBACK) ( struct acpi_gpe_xrupt_info *gpe_xrupt_info, struct acpi_gpe_block_info *gpe_block); @@ -495,7 +513,7 @@ struct acpi_thread_state struct acpi_walk_state *walk_state_list; /* Head of list of walk_states for this thread */ union acpi_operand_object *acquired_mutex_list; /* List of all currently acquired mutexes */ u32 thread_id; /* Running thread ID */ - u16 current_sync_level; /* Mutex Sync (nested acquire) level */ + u8 current_sync_level; /* Mutex Sync (nested acquire) level */ }; @@ -544,7 +562,7 @@ union acpi_generic_state struct acpi_scope_state scope; struct acpi_pscope_state parse_scope; struct acpi_pkg_state pkg; - struct acpi_thread_state acpi_thread; + struct acpi_thread_state thread; struct acpi_result_values results; struct acpi_notify_info notify; }; @@ -844,7 +862,6 @@ struct acpi_bit_register_info /* * Large resource descriptor types */ - #define ACPI_RDESC_TYPE_MEMORY_24 0x81 #define ACPI_RDESC_TYPE_GENERAL_REGISTER 0x82 #define ACPI_RDESC_TYPE_LARGE_VENDOR 0x84 @@ -854,6 +871,7 @@ struct acpi_bit_register_info #define ACPI_RDESC_TYPE_WORD_ADDRESS_SPACE 0x88 #define ACPI_RDESC_TYPE_EXTENDED_XRUPT 0x89 #define ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE 0x8A +#define ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE 0x8B /***************************************************************************** diff --git a/xen/include/acpi/acmacros.h b/xen/include/acpi/acmacros.h index e1abf964bf..fcaced16b1 100644 --- a/xen/include/acpi/acmacros.h +++ b/xen/include/acpi/acmacros.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2004, R. Byron Moore + * Copyright (C) 2000 - 2005, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -53,6 +53,10 @@ #define ACPI_LOBYTE(l) ((u8)(u16)(l)) #define ACPI_HIBYTE(l) ((u8)((((u16)(l)) >> 8) & 0xFF)) +#define ACPI_SET_BIT(target,bit) ((target) |= (bit)) +#define ACPI_CLEAR_BIT(target,bit) ((target) &= ~(bit)) +#define ACPI_MIN(a,b) (((a)<(b))?(a):(b)) + #if ACPI_MACHINE_WIDTH == 16 @@ -97,7 +101,7 @@ * printf() format helpers */ -/* Split 64-bit integer into two 32-bit values. use with %8,8_x%8.8X */ +/* Split 64-bit integer into two 32-bit values. Use with %8.8X%8.8X */ #define ACPI_FORMAT_UINT64(i) ACPI_HIDWORD(i),ACPI_LODWORD(i) @@ -361,24 +365,6 @@ #define ACPI_IS_OCTAL_DIGIT(d) (((char)(d) >= '0') && ((char)(d) <= '7')) -/* Macros for GAS addressing */ - -#if ACPI_MACHINE_WIDTH != 16 - -#define ACPI_PCI_DEVICE(a) (u16) ((ACPI_HIDWORD ((a))) & 0x0000FFFF) -#define ACPI_PCI_FUNCTION(a) (u16) ((ACPI_LODWORD ((a))) >> 16) -#define ACPI_PCI_REGISTER(a) (u16) ((ACPI_LODWORD ((a))) & 0x0000FFFF) - -#else - -/* No support for GAS and PCI IDs in 16-bit mode */ - -#define ACPI_PCI_FUNCTION(a) (u16) ((a) & 0xFFFF0000) -#define ACPI_PCI_DEVICE(a) (u16) ((a) & 0x0000FFFF) -#define ACPI_PCI_REGISTER(a) (u16) ((a) & 0x0000FFFF) - -#endif - /* Bitfields within ACPI registers */ @@ -502,19 +488,19 @@ * The first parameter should be the procedure name as a quoted string. This is declared * as a local string ("_proc_name) so that it can be also used by the function exit macros below. */ -#define ACPI_FUNCTION_NAME(a) struct acpi_debug_print_info _dbg; \ - _dbg.component_id = _COMPONENT; \ - _dbg.proc_name = a; \ - _dbg.module_name = _THIS_MODULE; +#define ACPI_FUNCTION_NAME(a) struct acpi_debug_print_info _debug_info; \ + _debug_info.component_id = _COMPONENT; \ + _debug_info.proc_name = a; \ + _debug_info.module_name = _THIS_MODULE; #define ACPI_FUNCTION_TRACE(a) ACPI_FUNCTION_NAME(a) \ - acpi_ut_trace(__LINE__,&_dbg) + acpi_ut_trace(__LINE__,&_debug_info) #define ACPI_FUNCTION_TRACE_PTR(a,b) ACPI_FUNCTION_NAME(a) \ - acpi_ut_trace_ptr(__LINE__,&_dbg,(void *)b) + acpi_ut_trace_ptr(__LINE__,&_debug_info,(void *)b) #define ACPI_FUNCTION_TRACE_U32(a,b) ACPI_FUNCTION_NAME(a) \ - acpi_ut_trace_u32(__LINE__,&_dbg,(u32)b) + acpi_ut_trace_u32(__LINE__,&_debug_info,(u32)b) #define ACPI_FUNCTION_TRACE_STR(a,b) ACPI_FUNCTION_NAME(a) \ - acpi_ut_trace_str(__LINE__,&_dbg,(char *)b) + acpi_ut_trace_str(__LINE__,&_debug_info,(char *)b) #define ACPI_FUNCTION_ENTRY() acpi_ut_track_stack_ptr() @@ -531,10 +517,10 @@ #define ACPI_DO_WHILE0(a) a #endif -#define return_VOID ACPI_DO_WHILE0 ({acpi_ut_exit(__LINE__,&_dbg);return;}) -#define return_ACPI_STATUS(s) ACPI_DO_WHILE0 ({acpi_ut_status_exit(__LINE__,&_dbg,(s));return((s));}) -#define return_VALUE(s) ACPI_DO_WHILE0 ({acpi_ut_value_exit(__LINE__,&_dbg,(acpi_integer)(s));return((s));}) -#define return_PTR(s) ACPI_DO_WHILE0 ({acpi_ut_ptr_exit(__LINE__,&_dbg,(u8 *)(s));return((s));}) +#define return_VOID ACPI_DO_WHILE0 ({acpi_ut_exit(__LINE__,&_debug_info);return;}) +#define return_ACPI_STATUS(s) ACPI_DO_WHILE0 ({acpi_ut_status_exit(__LINE__,&_debug_info,(s));return((s));}) +#define return_VALUE(s) ACPI_DO_WHILE0 ({acpi_ut_value_exit(__LINE__,&_debug_info,(acpi_integer)(s));return((s));}) +#define return_PTR(s) ACPI_DO_WHILE0 ({acpi_ut_ptr_exit(__LINE__,&_debug_info,(u8 *)(s));return((s));}) /* Conditional execution */ @@ -548,12 +534,16 @@ /* Stack and buffer dumping */ -#define ACPI_DUMP_STACK_ENTRY(a) acpi_ex_dump_operand(a) +#define ACPI_DUMP_STACK_ENTRY(a) acpi_ex_dump_operand((a),0) #define ACPI_DUMP_OPERANDS(a,b,c,d,e) acpi_ex_dump_operands(a,b,c,d,e,_THIS_MODULE,__LINE__) #define ACPI_DUMP_ENTRY(a,b) acpi_ns_dump_entry (a,b) + +#ifdef ACPI_FUTURE_USAGE #define ACPI_DUMP_TABLES(a,b) acpi_ns_dump_tables(a,b) +#endif + #define ACPI_DUMP_PATHNAME(a,b,c,d) acpi_ns_dump_pathname(a,b,c,d) #define ACPI_DUMP_RESOURCE_LIST(a) acpi_rs_dump_resource_list(a) #define ACPI_DUMP_BUFFER(a,b) acpi_ut_dump_buffer((u8 *)a,b,DB_BYTE_DISPLAY,_COMPONENT) @@ -606,7 +596,11 @@ #define ACPI_DUMP_STACK_ENTRY(a) #define ACPI_DUMP_OPERANDS(a,b,c,d,e) #define ACPI_DUMP_ENTRY(a,b) + +#ifdef ACPI_FUTURE_USAGE #define ACPI_DUMP_TABLES(a,b) +#endif + #define ACPI_DUMP_PATHNAME(a,b,c,d) #define ACPI_DUMP_RESOURCE_LIST(a) #define ACPI_DUMP_BUFFER(a,b) @@ -681,7 +675,4 @@ #endif /* ACPI_DBG_TRACK_ALLOCATIONS */ - -#define ACPI_GET_STACK_POINTER _asm {mov eax, ebx} - #endif /* ACMACROS_H */ diff --git a/xen/include/acpi/acobject.h b/xen/include/acpi/acobject.h index 6caaf6ade2..036023a940 100644 --- a/xen/include/acpi/acobject.h +++ b/xen/include/acpi/acobject.h @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2004, R. Byron Moore + * Copyright (C) 2000 - 2005, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -94,9 +94,7 @@ u32 bit_length; /* Length of field in bits */\ u32 base_byte_offset; /* Byte offset within containing object */\ u8 start_field_bit_offset;/* Bit offset within first field datum (0-63) */\ - u8 datum_valid_bits; /* Valid bit in first "Field datum" */\ - u8 end_field_valid_bits; /* Valid bits in the last "field datum" */\ - u8 end_buffer_valid_bits; /* Valid bits in the last "buffer datum" */\ + u8 access_bit_width; /* Read/Write size in bits (8-64) */\ u32 value; /* Value to store into the Bank or Index register */\ struct acpi_namespace_node *node; /* Link back to parent node */ @@ -135,7 +133,10 @@ struct acpi_object_integer acpi_integer value; }; - +/* + * Note: The String and Buffer object must be identical through the Pointer + * element. There is code that depends on this. + */ struct acpi_object_string /* Null terminated, ASCII characters only */ { ACPI_OBJECT_COMMON_HEADER @@ -180,7 +181,11 @@ struct acpi_object_event }; -#define INFINITE_CONCURRENCY 0xFF +#define ACPI_INFINITE_CONCURRENCY 0xFF + +typedef +acpi_status (*ACPI_INTERNAL_METHOD) ( + struct acpi_walk_state *walk_state); struct acpi_object_method { @@ -190,6 +195,7 @@ struct acpi_object_method u32 aml_length; void *semaphore; u8 *aml_start; + ACPI_INTERNAL_METHOD implementation; u8 concurrency; u8 thread_count; acpi_owner_id owning_id; @@ -199,13 +205,14 @@ struct acpi_object_method struct acpi_object_mutex { ACPI_OBJECT_COMMON_HEADER - u16 sync_level; - u16 acquisition_depth; - struct acpi_thread_state *owner_thread; - void *semaphore; + u8 sync_level; /* 0-15, specified in Mutex() call */ + u16 acquisition_depth; /* Allow multiple Acquires, same thread */ + struct acpi_thread_state *owner_thread; /* Current owner of the mutex */ + void *semaphore; /* Actual OS synchronization object */ union acpi_operand_object *prev; /* Link for list of acquired mutexes */ union acpi_operand_object *next; /* Link for list of acquired mutexes */ - struct acpi_namespace_node *node; /* containing object */ + struct acpi_namespace_node *node; /* Containing namespace node */ + u8 original_sync_level; /* Owner's original sync level (0-15) */ }; @@ -215,7 +222,7 @@ struct acpi_object_region u8 space_id; union acpi_operand_object *handler; /* Handler for region access */ - struct acpi_namespace_node *node; /* containing object */ + struct acpi_namespace_node *node; /* Containing namespace node */ union acpi_operand_object *next; u32 length; acpi_physical_address address; diff --git a/xen/include/acpi/acoutput.h b/xen/include/acpi/acoutput.h index 0ed98ae4d3..2fbe180fee 100644 --- a/xen/include/acpi/acoutput.h +++ b/xen/include/acpi/acoutput.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2004, R. Byron Moore + * Copyright (C) 2000 - 2005, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -136,7 +136,7 @@ /* * Debug level macros that are used in the DEBUG_PRINT macros */ -#define ACPI_DEBUG_LEVEL(dl) (u32) dl,__LINE__,&_dbg +#define ACPI_DEBUG_LEVEL(dl) (u32) dl,__LINE__,&_debug_info /* Exception level -- used in the global "debug_level" */ diff --git a/xen/include/acpi/acpi.h b/xen/include/acpi/acpi.h index bb5bd8f03e..ad53252dd4 100644 --- a/xen/include/acpi/acpi.h +++ b/xen/include/acpi/acpi.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2004, R. Byron Moore + * Copyright (C) 2000 - 2005, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/xen/include/acpi/acpi_bus.h b/xen/include/acpi/acpi_bus.h index 4326bc934b..a4197e9abe 100644 --- a/xen/include/acpi/acpi_bus.h +++ b/xen/include/acpi/acpi_bus.h @@ -26,16 +26,10 @@ #ifndef __ACPI_BUS_H__ #define __ACPI_BUS_H__ -#if 0 -#include -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,4)) -#include -#define CONFIG_LDM -#endif -#endif /* 0 */ - #include +#define PREFIX "ACPI: " + /* TBD: Make dynamic */ #define ACPI_MAX_HANDLES 10 struct acpi_handle_list { @@ -66,10 +60,10 @@ acpi_evaluate_reference ( #ifdef CONFIG_ACPI_BUS -/*#include */ +#include #define ACPI_BUS_FILE_ROOT "acpi" -/*extern struct proc_dir_entry *acpi_root_dir;*/ +extern struct proc_dir_entry *acpi_root_dir; extern FADT_DESCRIPTOR acpi_fadt; enum acpi_bus_removal_type { @@ -108,6 +102,9 @@ typedef int (*acpi_op_suspend) (struct acpi_device *device, int state); typedef int (*acpi_op_resume) (struct acpi_device *device, int state); typedef int (*acpi_op_scan) (struct acpi_device *device); typedef int (*acpi_op_bind) (struct acpi_device *device); +typedef int (*acpi_op_unbind) (struct acpi_device *device); +typedef int (*acpi_op_match) (struct acpi_device *device, + struct acpi_driver *driver); struct acpi_device_ops { acpi_op_add add; @@ -119,13 +116,15 @@ struct acpi_device_ops { acpi_op_resume resume; acpi_op_scan scan; acpi_op_bind bind; + acpi_op_unbind unbind; + acpi_op_match match; }; struct acpi_driver { struct list_head node; char name[80]; char class[80]; - int references; + atomic_t references; char *ids; /* Supported Hardware IDs */ struct acpi_device_ops ops; }; @@ -161,7 +160,8 @@ struct acpi_device_flags { u32 suprise_removal_ok:1; u32 power_manageable:1; u32 performance_manageable:1; - u32 reserved:21; + u32 wake_capable:1; /* Wakeup(_PRW) supported? */ + u32 reserved:20; }; @@ -207,10 +207,8 @@ struct acpi_device_power_flags { u32 explicit_get:1; /* _PSC present? */ u32 power_resources:1; /* Power resources */ u32 inrush_current:1; /* Serialize Dx->D0 */ - u32 wake_capable:1; /* Wakeup supported? */ - u32 wake_enabled:1; /* Enabled for wakeup */ u32 power_removed:1; /* Optimize Dx->D0 */ - u32 reserved:26; + u32 reserved:28; }; struct acpi_device_power_state { @@ -254,6 +252,25 @@ struct acpi_device_perf { struct acpi_device_perf_state *states; }; +/* Wakeup Management */ +struct acpi_device_wakeup_flags { + u8 valid:1; /* Can successfully enable wakeup? */ + u8 run_wake:1; /* Run-Wake GPE devices */ +}; + +struct acpi_device_wakeup_state { + u8 enabled:1; + u8 active:1; +}; + +struct acpi_device_wakeup { + acpi_handle gpe_device; + acpi_integer gpe_number;; + acpi_integer sleep_state; + struct acpi_handle_list resources; + struct acpi_device_wakeup_state state; + struct acpi_device_wakeup_flags flags; +}; /* Device */ @@ -262,18 +279,19 @@ struct acpi_device { struct acpi_device *parent; struct list_head children; struct list_head node; + struct list_head wakeup_list; + struct list_head g_list; struct acpi_device_status status; struct acpi_device_flags flags; struct acpi_device_pnp pnp; struct acpi_device_power power; + struct acpi_device_wakeup wakeup; struct acpi_device_perf performance; struct acpi_device_dir dir; struct acpi_device_ops ops; struct acpi_driver *driver; void *driver_data; -#ifdef CONFIG_LDM - struct device dev; -#endif + struct kobject kobj; }; #define acpi_driver_data(d) ((d)->driver_data) @@ -292,12 +310,14 @@ struct acpi_bus_event { u32 data; }; +extern struct subsystem acpi_subsys; /* * External Functions */ -int acpi_bus_get_device(acpi_handle, struct acpi_device **device); +int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device); +void acpi_bus_data_handler(acpi_handle handle, u32 function, void *context); int acpi_bus_get_status (struct acpi_device *device); int acpi_bus_get_power (acpi_handle handle, int *state); int acpi_bus_set_power (acpi_handle handle, int state); @@ -305,10 +325,15 @@ int acpi_bus_generate_event (struct acpi_device *device, u8 type, int data); int acpi_bus_receive_event (struct acpi_bus_event *event); int acpi_bus_register_driver (struct acpi_driver *driver); int acpi_bus_unregister_driver (struct acpi_driver *driver); -int acpi_bus_scan (struct acpi_device *device); -int acpi_init (void); -void acpi_exit (void); +int acpi_bus_scan (struct acpi_device *start); +int acpi_bus_trim(struct acpi_device *start, int rmdevice); +int acpi_bus_add (struct acpi_device **child, struct acpi_device *parent, + acpi_handle handle, int type); + +int acpi_match_ids (struct acpi_device *device, char *ids); +int acpi_create_dir(struct acpi_device *); +void acpi_remove_dir(struct acpi_device *); #endif /*CONFIG_ACPI_BUS*/ diff --git a/xen/include/acpi/acpi_drivers.h b/xen/include/acpi/acpi_drivers.h index 3b5273a230..c26d5ea5b1 100644 --- a/xen/include/acpi/acpi_drivers.h +++ b/xen/include/acpi/acpi_drivers.h @@ -1,5 +1,5 @@ /* - * acpi_drivers.h ($Revision: 32 $) + * acpi_drivers.h ($Revision: 31 $) * * Copyright (C) 2001, 2002 Andy Grover * Copyright (C) 2001, 2002 Paul Diefenbaugh @@ -27,122 +27,22 @@ #define __ACPI_DRIVERS_H__ #include -#include "acpi_bus.h" +#include #define ACPI_MAX_STRING 80 - -/* -------------------------------------------------------------------------- - ACPI Bus - -------------------------------------------------------------------------- */ - #define ACPI_BUS_COMPONENT 0x00010000 -#define ACPI_BUS_CLASS "system_bus" -#define ACPI_BUS_HID "ACPI_BUS" -#define ACPI_BUS_DRIVER_NAME "ACPI Bus Driver" -#define ACPI_BUS_DEVICE_NAME "System Bus" - - -/* -------------------------------------------------------------------------- - AC Adapter - -------------------------------------------------------------------------- */ - -#define ACPI_AC_COMPONENT 0x00020000 -#define ACPI_AC_CLASS "ac_adapter" -#define ACPI_AC_HID "ACPI0003" -#define ACPI_AC_DRIVER_NAME "ACPI AC Adapter Driver" -#define ACPI_AC_DEVICE_NAME "AC Adapter" -#define ACPI_AC_FILE_STATE "state" -#define ACPI_AC_NOTIFY_STATUS 0x80 -#define ACPI_AC_STATUS_OFFLINE 0x00 -#define ACPI_AC_STATUS_ONLINE 0x01 -#define ACPI_AC_STATUS_UNKNOWN 0xFF - - -/* -------------------------------------------------------------------------- - Battery - -------------------------------------------------------------------------- */ - -#define ACPI_BATTERY_COMPONENT 0x00040000 -#define ACPI_BATTERY_CLASS "battery" -#define ACPI_BATTERY_HID "PNP0C0A" -#define ACPI_BATTERY_DRIVER_NAME "ACPI Battery Driver" -#define ACPI_BATTERY_DEVICE_NAME "Battery" -#define ACPI_BATTERY_FILE_INFO "info" -#define ACPI_BATTERY_FILE_STATUS "state" -#define ACPI_BATTERY_FILE_ALARM "alarm" -#define ACPI_BATTERY_NOTIFY_STATUS 0x80 -#define ACPI_BATTERY_NOTIFY_INFO 0x81 -#define ACPI_BATTERY_UNITS_WATTS "mW" -#define ACPI_BATTERY_UNITS_AMPS "mA" - - -/* -------------------------------------------------------------------------- - Button - -------------------------------------------------------------------------- */ +#define ACPI_SYSTEM_COMPONENT 0x02000000 -#define ACPI_BUTTON_COMPONENT 0x00080000 -#define ACPI_BUTTON_DRIVER_NAME "ACPI Button Driver" -#define ACPI_BUTTON_CLASS "button" -#define ACPI_BUTTON_FILE_INFO "info" -#define ACPI_BUTTON_FILE_STATE "state" -#define ACPI_BUTTON_TYPE_UNKNOWN 0x00 -#define ACPI_BUTTON_NOTIFY_STATUS 0x80 +/* _HID definitions */ -#define ACPI_BUTTON_SUBCLASS_POWER "power" -#define ACPI_BUTTON_HID_POWER "PNP0C0C" +#define ACPI_POWER_HID "ACPI_PWR" +#define ACPI_PROCESSOR_HID "ACPI_CPU" +#define ACPI_SYSTEM_HID "ACPI_SYS" +#define ACPI_THERMAL_HID "ACPI_THM" #define ACPI_BUTTON_HID_POWERF "ACPI_FPB" -#define ACPI_BUTTON_DEVICE_NAME_POWER "Power Button (CM)" -#define ACPI_BUTTON_DEVICE_NAME_POWERF "Power Button (FF)" -#define ACPI_BUTTON_TYPE_POWER 0x01 -#define ACPI_BUTTON_TYPE_POWERF 0x02 - -#define ACPI_BUTTON_SUBCLASS_SLEEP "sleep" -#define ACPI_BUTTON_HID_SLEEP "PNP0C0E" #define ACPI_BUTTON_HID_SLEEPF "ACPI_FSB" -#define ACPI_BUTTON_DEVICE_NAME_SLEEP "Sleep Button (CM)" -#define ACPI_BUTTON_DEVICE_NAME_SLEEPF "Sleep Button (FF)" -#define ACPI_BUTTON_TYPE_SLEEP 0x03 -#define ACPI_BUTTON_TYPE_SLEEPF 0x04 - -#define ACPI_BUTTON_SUBCLASS_LID "lid" -#define ACPI_BUTTON_HID_LID "PNP0C0D" -#define ACPI_BUTTON_DEVICE_NAME_LID "Lid Switch" -#define ACPI_BUTTON_TYPE_LID 0x05 - - -/* -------------------------------------------------------------------------- - Embedded Controller - -------------------------------------------------------------------------- */ - -#define ACPI_EC_COMPONENT 0x00100000 -#define ACPI_EC_CLASS "embedded_controller" -#define ACPI_EC_HID "PNP0C09" -#define ACPI_EC_DRIVER_NAME "ACPI Embedded Controller Driver" -#define ACPI_EC_DEVICE_NAME "Embedded Controller" -#define ACPI_EC_FILE_INFO "info" - -#ifdef CONFIG_ACPI_EC - -int acpi_ec_ecdt_probe (void); -int acpi_ec_init (void); -void acpi_ec_exit (void); - -#endif - - -/* -------------------------------------------------------------------------- - Fan - -------------------------------------------------------------------------- */ - -#define ACPI_FAN_COMPONENT 0x00200000 -#define ACPI_FAN_CLASS "fan" -#define ACPI_FAN_HID "PNP0C0B" -#define ACPI_FAN_DRIVER_NAME "ACPI Fan Driver" -#define ACPI_FAN_DEVICE_NAME "Fan" -#define ACPI_FAN_FILE_STATE "state" -#define ACPI_FAN_NOTIFY_STATUS 0x80 /* -------------------------------------------------------------------------- @@ -153,41 +53,28 @@ void acpi_ec_exit (void); #define ACPI_PCI_COMPONENT 0x00400000 -/* ACPI PCI Root Bridge (pci_root.c) */ - -#define ACPI_PCI_ROOT_CLASS "pci_bridge" -#define ACPI_PCI_ROOT_HID "PNP0A03" -#define ACPI_PCI_ROOT_DRIVER_NAME "ACPI PCI Root Bridge Driver" -#define ACPI_PCI_ROOT_DEVICE_NAME "PCI Root Bridge" - -int acpi_pci_root_init (void); -void acpi_pci_root_exit (void); - /* ACPI PCI Interrupt Link (pci_link.c) */ -#define ACPI_PCI_LINK_CLASS "pci_irq_routing" -#define ACPI_PCI_LINK_HID "PNP0C0F" -#define ACPI_PCI_LINK_DRIVER_NAME "ACPI PCI Interrupt Link Driver" -#define ACPI_PCI_LINK_DEVICE_NAME "PCI Interrupt Link" -#define ACPI_PCI_LINK_FILE_INFO "info" -#define ACPI_PCI_LINK_FILE_STATUS "state" - -int acpi_pci_link_check (void); +int acpi_irq_penalty_init (void); int acpi_pci_link_get_irq (acpi_handle handle, int index, int* edge_level, int* active_high_low); -int acpi_pci_link_init (void); -void acpi_pci_link_exit (void); /* ACPI PCI Interrupt Routing (pci_irq.c) */ int acpi_pci_irq_add_prt (acpi_handle handle, int segment, int bus); +void acpi_pci_irq_del_prt (int segment, int bus); /* ACPI PCI Device Binding (pci_bind.c) */ struct pci_bus; int acpi_pci_bind (struct acpi_device *device); +int acpi_pci_unbind (struct acpi_device *device); int acpi_pci_bind_root (struct acpi_device *device, struct acpi_pci_id *id, struct pci_bus *bus); +/* Arch-defined function to add a bus to the system */ + +struct pci_bus *pci_acpi_scan_root(struct acpi_device *device, int domain, int bus); + #endif /*CONFIG_ACPI_PCI*/ @@ -195,43 +82,25 @@ int acpi_pci_bind_root (struct acpi_device *device, struct acpi_pci_id *id, stru Power Resource -------------------------------------------------------------------------- */ -#define ACPI_POWER_COMPONENT 0x00800000 -#define ACPI_POWER_CLASS "power_resource" -#define ACPI_POWER_HID "ACPI_PWR" -#define ACPI_POWER_DRIVER_NAME "ACPI Power Resource Driver" -#define ACPI_POWER_DEVICE_NAME "Power Resource" -#define ACPI_POWER_FILE_INFO "info" -#define ACPI_POWER_FILE_STATUS "state" -#define ACPI_POWER_RESOURCE_STATE_OFF 0x00 -#define ACPI_POWER_RESOURCE_STATE_ON 0x01 -#define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF - #ifdef CONFIG_ACPI_POWER - +int acpi_enable_wakeup_device_power (struct acpi_device *dev); +int acpi_disable_wakeup_device_power (struct acpi_device *dev); int acpi_power_get_inferred_state (struct acpi_device *device); int acpi_power_transition (struct acpi_device *device, int state); -int acpi_power_init (void); -void acpi_power_exit (void); - #endif +/* -------------------------------------------------------------------------- + Embedded Controller + -------------------------------------------------------------------------- */ +#ifdef CONFIG_ACPI_EC +int acpi_ec_ecdt_probe (void); +#endif + /* -------------------------------------------------------------------------- Processor -------------------------------------------------------------------------- */ -#define ACPI_PROCESSOR_COMPONENT 0x01000000 -#define ACPI_PROCESSOR_CLASS "processor" -#define ACPI_PROCESSOR_HID "ACPI_CPU" -#define ACPI_PROCESSOR_DRIVER_NAME "ACPI Processor Driver" -#define ACPI_PROCESSOR_DEVICE_NAME "Processor" -#define ACPI_PROCESSOR_FILE_INFO "info" -#define ACPI_PROCESSOR_FILE_POWER "power" -#define ACPI_PROCESSOR_FILE_PERFORMANCE "performance" -#define ACPI_PROCESSOR_FILE_THROTTLING "throttling" -#define ACPI_PROCESSOR_FILE_LIMIT "limit" -#define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80 -#define ACPI_PROCESSOR_NOTIFY_POWER 0x81 #define ACPI_PROCESSOR_LIMIT_NONE 0x00 #define ACPI_PROCESSOR_LIMIT_INCREMENT 0x01 #define ACPI_PROCESSOR_LIMIT_DECREMENT 0x02 @@ -239,109 +108,4 @@ void acpi_power_exit (void); int acpi_processor_set_thermal_limit(acpi_handle handle, int type); -/* -------------------------------------------------------------------------- - System - -------------------------------------------------------------------------- */ - -#define ACPI_SYSTEM_COMPONENT 0x02000000 -#define ACPI_SYSTEM_CLASS "system" -#define ACPI_SYSTEM_HID "ACPI_SYS" -#define ACPI_SYSTEM_DRIVER_NAME "ACPI System Driver" -#define ACPI_SYSTEM_DEVICE_NAME "System" -#define ACPI_SYSTEM_FILE_INFO "info" -#define ACPI_SYSTEM_FILE_EVENT "event" -#define ACPI_SYSTEM_FILE_ALARM "alarm" -#define ACPI_SYSTEM_FILE_DSDT "dsdt" -#define ACPI_SYSTEM_FILE_FADT "fadt" -#define ACPI_SYSTEM_FILE_SLEEP "sleep" -#define ACPI_SYSTEM_FILE_DEBUG_LAYER "debug_layer" -#define ACPI_SYSTEM_FILE_DEBUG_LEVEL "debug_level" - -#ifdef CONFIG_ACPI_SYSTEM - -int acpi_system_init (void); -void acpi_system_exit (void); - -#endif - - -/* -------------------------------------------------------------------------- - Thermal Zone - -------------------------------------------------------------------------- */ - -#define ACPI_THERMAL_COMPONENT 0x04000000 -#define ACPI_THERMAL_CLASS "thermal_zone" -#define ACPI_THERMAL_HID "ACPI_THM" -#define ACPI_THERMAL_DRIVER_NAME "ACPI Thermal Zone Driver" -#define ACPI_THERMAL_DEVICE_NAME "Thermal Zone" -#define ACPI_THERMAL_FILE_STATE "state" -#define ACPI_THERMAL_FILE_TEMPERATURE "temperature" -#define ACPI_THERMAL_FILE_TRIP_POINTS "trip_points" -#define ACPI_THERMAL_FILE_COOLING_MODE "cooling_mode" -#define ACPI_THERMAL_FILE_POLLING_FREQ "polling_frequency" -#define ACPI_THERMAL_NOTIFY_TEMPERATURE 0x80 -#define ACPI_THERMAL_NOTIFY_THRESHOLDS 0x81 -#define ACPI_THERMAL_NOTIFY_DEVICES 0x82 -#define ACPI_THERMAL_NOTIFY_CRITICAL 0xF0 -#define ACPI_THERMAL_NOTIFY_HOT 0xF1 -#define ACPI_THERMAL_MODE_ACTIVE 0x00 -#define ACPI_THERMAL_MODE_PASSIVE 0x01 -#define ACPI_THERMAL_PATH_POWEROFF "/sbin/poweroff" - - -/* -------------------------------------------------------------------------- - Debug Support - -------------------------------------------------------------------------- */ - -#define ACPI_DEBUG_RESTORE 0 -#define ACPI_DEBUG_LOW 1 -#define ACPI_DEBUG_MEDIUM 2 -#define ACPI_DEBUG_HIGH 3 -#define ACPI_DEBUG_DRIVERS 4 - -/*extern u32 acpi_dbg_level;*/ -/*extern u32 acpi_dbg_layer;*/ - -static inline void -acpi_set_debug ( - u32 flag) -{ - static u32 layer_save; - static u32 level_save; - - switch (flag) { - case ACPI_DEBUG_RESTORE: - acpi_dbg_layer = layer_save; - acpi_dbg_level = level_save; - break; - case ACPI_DEBUG_LOW: - case ACPI_DEBUG_MEDIUM: - case ACPI_DEBUG_HIGH: - case ACPI_DEBUG_DRIVERS: - layer_save = acpi_dbg_layer; - level_save = acpi_dbg_level; - break; - } - - switch (flag) { - case ACPI_DEBUG_LOW: - acpi_dbg_layer = ACPI_COMPONENT_DEFAULT | ACPI_ALL_DRIVERS; - acpi_dbg_level = ACPI_DEBUG_DEFAULT; - break; - case ACPI_DEBUG_MEDIUM: - acpi_dbg_layer = ACPI_COMPONENT_DEFAULT | ACPI_ALL_DRIVERS; - acpi_dbg_level = ACPI_LV_FUNCTIONS | ACPI_LV_ALL_EXCEPTIONS; - break; - case ACPI_DEBUG_HIGH: - acpi_dbg_layer = 0xFFFFFFFF; - acpi_dbg_level = 0xFFFFFFFF; - break; - case ACPI_DEBUG_DRIVERS: - acpi_dbg_layer = ACPI_ALL_DRIVERS; - acpi_dbg_level = 0xFFFFFFFF; - break; - } -} - - #endif /*__ACPI_DRIVERS_H__*/ diff --git a/xen/include/acpi/acpiosxf.h b/xen/include/acpi/acpiosxf.h index 6f485231ac..57779919c1 100644 --- a/xen/include/acpi/acpiosxf.h +++ b/xen/include/acpi/acpiosxf.h @@ -9,7 +9,7 @@ /* - * Copyright (C) 2000 - 2004, R. Byron Moore + * Copyright (C) 2000 - 2005, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -169,17 +169,19 @@ acpi_status acpi_os_map_memory ( acpi_physical_address physical_address, acpi_size size, - void **logical_address); + void __iomem **logical_address); void acpi_os_unmap_memory ( - void *logical_address, + void __iomem *logical_address, acpi_size size); +#ifdef ACPI_FUTURE_USAGE acpi_status acpi_os_get_physical_address ( void *logical_address, acpi_physical_address *physical_address); +#endif /* @@ -188,14 +190,14 @@ acpi_os_get_physical_address ( acpi_status acpi_os_install_interrupt_handler ( - u32 interrupt_number, - OSD_HANDLER service_routine, + u32 gsi, + acpi_osd_handler service_routine, void *context); acpi_status acpi_os_remove_interrupt_handler ( - u32 interrupt_number, - OSD_HANDLER service_routine); + u32 gsi, + acpi_osd_handler service_routine); /* @@ -209,13 +211,16 @@ acpi_os_get_thread_id ( acpi_status acpi_os_queue_for_execution ( u32 priority, - OSD_EXECUTION_CALLBACK function, + acpi_osd_exec_callback function, + void *context); + +void +acpi_os_wait_events_complete ( void *context); void acpi_os_sleep ( - u32 seconds, - u32 milliseconds); + acpi_integer milliseconds); void acpi_os_stall ( @@ -258,25 +263,28 @@ acpi_os_write_memory ( /* * Platform and hardware-independent PCI configuration space access + * Note: Can't use "Register" as a parameter, changed to "Reg" -- + * certain compilers complain. */ acpi_status acpi_os_read_pci_configuration ( struct acpi_pci_id *pci_id, - u32 register, + u32 reg, void *value, u32 width); acpi_status acpi_os_write_pci_configuration ( struct acpi_pci_id *pci_id, - u32 register, + u32 reg, acpi_integer value, u32 width); /* * Interim function needed for PCI IRQ routing */ + void acpi_os_derive_pci_id( acpi_handle rhandle, @@ -292,12 +300,14 @@ acpi_os_readable ( void *pointer, acpi_size length); +#ifdef ACPI_FUTURE_USAGE u8 acpi_os_writable ( void *pointer, acpi_size length); +#endif -u32 +u64 acpi_os_get_timer ( void); @@ -329,9 +339,11 @@ acpi_os_redirect_output ( * Debug input */ +#ifdef ACPI_FUTURE_USAGE u32 acpi_os_get_line ( char *buffer); +#endif /* diff --git a/xen/include/acpi/acpixf.h b/xen/include/acpi/acpixf.h index fcebceb3e2..00d78b7965 100644 --- a/xen/include/acpi/acpixf.h +++ b/xen/include/acpi/acpixf.h @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2004, R. Byron Moore + * Copyright (C) 2000 - 2005, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -70,9 +70,11 @@ acpi_status acpi_terminate ( void); +#ifdef ACPI_FUTURE_USAGE acpi_status acpi_subsystem_status ( void); +#endif acpi_status acpi_enable ( @@ -82,9 +84,11 @@ acpi_status acpi_disable ( void); +#ifdef ACPI_FUTURE_USAGE acpi_status acpi_get_system_info ( struct acpi_buffer *ret_buffer); +#endif const char * acpi_format_exception ( @@ -94,10 +98,12 @@ acpi_status acpi_purge_cached_objects ( void); +#ifdef ACPI_FUTURE_USAGE acpi_status acpi_install_initialization_handler ( acpi_init_handler handler, u32 function); +#endif /* * ACPI Memory manager @@ -129,6 +135,7 @@ acpi_status acpi_load_tables ( void); +#ifdef ACPI_FUTURE_USAGE acpi_status acpi_load_table ( struct acpi_table_header *table_ptr); @@ -142,6 +149,7 @@ acpi_get_table_header ( acpi_table_type table_type, u32 instance, struct acpi_table_header *out_table_header); +#endif /* ACPI_FUTURE_USAGE */ acpi_status acpi_get_table ( @@ -218,6 +226,7 @@ acpi_evaluate_object ( struct acpi_object_list *parameter_objects, struct acpi_buffer *return_object_buffer); +#ifdef ACPI_FUTURE_USAGE acpi_status acpi_evaluate_object_typed ( acpi_handle object, @@ -225,6 +234,7 @@ acpi_evaluate_object_typed ( struct acpi_object_list *external_params, struct acpi_buffer *return_buffer, acpi_object_type return_type); +#endif acpi_status acpi_get_object_info ( @@ -296,9 +306,20 @@ acpi_install_gpe_handler ( acpi_handle gpe_device, u32 gpe_number, u32 type, - acpi_gpe_handler handler, + acpi_event_handler address, void *context); +#ifdef ACPI_FUTURE_USAGE +acpi_status +acpi_install_exception_handler ( + acpi_exception_handler handler); +#endif + + +/* + * Event interfaces + */ + acpi_status acpi_acquire_global_lock ( u16 timeout, @@ -312,7 +333,7 @@ acpi_status acpi_remove_gpe_handler ( acpi_handle gpe_device, u32 gpe_number, - acpi_gpe_handler handler); + acpi_event_handler address); acpi_status acpi_enable_event ( @@ -328,10 +349,18 @@ acpi_status acpi_clear_event ( u32 event); +#ifdef ACPI_FUTURE_USAGE acpi_status acpi_get_event_status ( u32 event, acpi_event_status *event_status); +#endif /* ACPI_FUTURE_USAGE */ + +acpi_status +acpi_set_gpe_type ( + acpi_handle gpe_device, + u32 gpe_number, + u8 type); acpi_status acpi_enable_gpe ( @@ -351,12 +380,14 @@ acpi_clear_gpe ( u32 gpe_number, u32 flags); +#ifdef ACPI_FUTURE_USAGE acpi_status acpi_get_gpe_status ( acpi_handle gpe_device, u32 gpe_number, u32 flags, acpi_event_status *event_status); +#endif /* ACPI_FUTURE_USAGE */ acpi_status acpi_install_gpe_block ( @@ -385,10 +416,12 @@ acpi_get_current_resources( acpi_handle device_handle, struct acpi_buffer *ret_buffer); +#ifdef ACPI_FUTURE_USAGE acpi_status acpi_get_possible_resources( acpi_handle device_handle, struct acpi_buffer *ret_buffer); +#endif acpi_status acpi_walk_resources ( @@ -432,9 +465,11 @@ acpi_status acpi_set_firmware_waking_vector ( acpi_physical_address physical_address); +#ifdef ACPI_FUTURE_USAGE acpi_status acpi_get_firmware_waking_vector ( acpi_physical_address *physical_address); +#endif acpi_status acpi_get_sleep_type_data ( @@ -446,11 +481,11 @@ acpi_status acpi_enter_sleep_state_prep ( u8 sleep_state); -acpi_status +acpi_status asmlinkage acpi_enter_sleep_state ( u8 sleep_state); -acpi_status +acpi_status asmlinkage acpi_enter_sleep_state_s4bios ( void); diff --git a/xen/include/acpi/acstruct.h b/xen/include/acpi/acstruct.h index c746cb9c3b..6b2284c9e8 100644 --- a/xen/include/acpi/acstruct.h +++ b/xen/include/acpi/acstruct.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2004, R. Byron Moore + * Copyright (C) 2000 - 2005, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -69,13 +69,14 @@ struct acpi_walk_state { u8 data_type; /* To differentiate various internal objs MUST BE FIRST!*/\ + u8 walk_type; acpi_owner_id owner_id; /* Owner of objects created during the walk */ u8 last_predicate; /* Result of last predicate */ + u8 reserved; /* For alignment */ u8 current_result; /* */ u8 next_op_info; /* Info about next_op */ u8 num_operands; /* Stack pointer for Operands[] array */ u8 return_used; - u8 walk_type; u16 opcode; /* Current AML opcode */ u8 scope_depth; u8 reserved1; @@ -91,7 +92,8 @@ struct acpi_walk_state struct acpi_namespace_node arguments[ACPI_METHOD_NUM_ARGS]; /* Control method arguments */ union acpi_operand_object **caller_return_desc; union acpi_generic_state *control_state; /* List of control states (nested IFs) */ - struct acpi_namespace_node *deferred_node; /* Used when executing deferred opcodes */ + struct acpi_namespace_node *deferred_node; /* Used when executing deferred opcodes */ + struct acpi_gpe_event_info *gpe_event_info; /* Info for GPE (_Lxx/_Exx methods only */ struct acpi_namespace_node local_variables[ACPI_METHOD_NUM_LOCALS]; /* Control method locals */ struct acpi_namespace_node *method_call_node; /* Called method Node*/ union acpi_parse_object *method_call_op; /* method_call Op if running a method */ @@ -112,7 +114,7 @@ struct acpi_walk_state union acpi_parse_object *next_op; /* next op to be processed */ acpi_parse_downwards descending_callback; acpi_parse_upwards ascending_callback; - struct acpi_thread_state *acpi_thread; + struct acpi_thread_state *thread; struct acpi_walk_state *next; /* Next walk_state in list */ }; @@ -200,4 +202,21 @@ union acpi_aml_operands }; +/* Internal method parameter list */ + +struct acpi_parameter_info +{ + struct acpi_namespace_node *node; + union acpi_operand_object **parameters; + union acpi_operand_object *return_object; + u8 parameter_type; + u8 return_object_type; +}; + +/* Types for parameter_type above */ + +#define ACPI_PARAM_ARGS 0 +#define ACPI_PARAM_GPE 1 + + #endif diff --git a/xen/include/acpi/actbl.h b/xen/include/acpi/actbl.h index 55680ad34b..f39ed91b5b 100644 --- a/xen/include/acpi/actbl.h +++ b/xen/include/acpi/actbl.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2004, R. Byron Moore + * Copyright (C) 2000 - 2005, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -288,19 +288,6 @@ struct smart_battery_table }; -/* - * High performance timer - */ -struct hpet_table -{ - ACPI_TABLE_HEADER_DEF - u32 hardware_id; - u32 base_address [3]; - u8 hpet_number; - u16 clock_tick; - u8 attributes; -}; - #pragma pack() @@ -343,5 +330,23 @@ struct acpi_table_support #include "actbl1.h" /* Acpi 1.0 table definitions */ #include "actbl2.h" /* Acpi 2.0 table definitions */ +extern u8 acpi_fadt_is_v1; /* is set to 1 if FADT is revision 1, + * needed for certain workarounds */ + +#pragma pack(1) +/* + * High performance timer + */ +struct hpet_table +{ + ACPI_TABLE_HEADER_DEF + u32 hardware_id; + struct acpi_generic_address base_address; + u8 hpet_number; + u16 clock_tick; + u8 attributes; +}; + +#pragma pack() #endif /* __ACTBL_H__ */ diff --git a/xen/include/acpi/actbl1.h b/xen/include/acpi/actbl1.h index 0db07c3291..33de5f4d2c 100644 --- a/xen/include/acpi/actbl1.h +++ b/xen/include/acpi/actbl1.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2004, R. Byron Moore + * Copyright (C) 2000 - 2005, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/xen/include/acpi/actbl2.h b/xen/include/acpi/actbl2.h index 188cedb529..ea3ca08d88 100644 --- a/xen/include/acpi/actbl2.h +++ b/xen/include/acpi/actbl2.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2004, R. Byron Moore + * Copyright (C) 2000 - 2005, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -62,6 +62,7 @@ #define BAF_8042_KEYBOARD_CONTROLLER 0x0002 #define FADT2_REVISION_ID 3 +#define FADT2_MINUS_REVISION_ID 2 #pragma pack(1) @@ -114,53 +115,56 @@ struct acpi_generic_address u8 address_space_id; /* Address space where struct or register exists. */ u8 register_bit_width; /* Size in bits of given register */ u8 register_bit_offset; /* Bit offset within the register */ - u8 reserved; /* Must be 0 */ + u8 access_width; /* Minimum Access size (ACPI 3.0) */ u64 address; /* 64-bit address of struct or register */ }; +#define FADT_REV2_COMMON \ + u32 V1_firmware_ctrl; /* 32-bit physical address of FACS */ \ + u32 V1_dsdt; /* 32-bit physical address of DSDT */ \ + u8 reserved1; /* System Interrupt Model isn't used in ACPI 2.0*/ \ + u8 prefer_PM_profile; /* Conveys preferred power management profile to OSPM. */ \ + u16 sci_int; /* System vector of SCI interrupt */ \ + u32 smi_cmd; /* Port address of SMI command port */ \ + u8 acpi_enable; /* Value to write to smi_cmd to enable ACPI */ \ + u8 acpi_disable; /* Value to write to smi_cmd to disable ACPI */ \ + u8 S4bios_req; /* Value to write to SMI CMD to enter S4BIOS state */ \ + u8 pstate_cnt; /* Processor performance state control*/ \ + u32 V1_pm1a_evt_blk; /* Port address of Power Mgt 1a acpi_event Reg Blk */ \ + u32 V1_pm1b_evt_blk; /* Port address of Power Mgt 1b acpi_event Reg Blk */ \ + u32 V1_pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */ \ + u32 V1_pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */ \ + u32 V1_pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */ \ + u32 V1_pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */ \ + u32 V1_gpe0_blk; /* Port addr of General Purpose acpi_event 0 Reg Blk */ \ + u32 V1_gpe1_blk; /* Port addr of General Purpose acpi_event 1 Reg Blk */ \ + u8 pm1_evt_len; /* Byte length of ports at pm1_x_evt_blk */ \ + u8 pm1_cnt_len; /* Byte length of ports at pm1_x_cnt_blk */ \ + u8 pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */ \ + u8 pm_tm_len; /* Byte Length of ports at pm_tm_blk */ \ + u8 gpe0_blk_len; /* Byte Length of ports at gpe0_blk */ \ + u8 gpe1_blk_len; /* Byte Length of ports at gpe1_blk */ \ + u8 gpe1_base; /* Offset in gpe model where gpe1 events start */ \ + u8 cst_cnt; /* Support for the _CST object and C States change notification.*/ \ + u16 plvl2_lat; /* Worst case HW latency to enter/exit C2 state */ \ + u16 plvl3_lat; /* Worst case HW latency to enter/exit C3 state */ \ + u16 flush_size; /* Number of flush strides that need to be read */ \ + u16 flush_stride; /* Processor's memory cache line width, in bytes */ \ + u8 duty_offset; /* Processor's duty cycle index in processor's P_CNT reg*/ \ + u8 duty_width; /* Processor's duty cycle value bit width in P_CNT register.*/ \ + u8 day_alrm; /* Index to day-of-month alarm in RTC CMOS RAM */ \ + u8 mon_alrm; /* Index to month-of-year alarm in RTC CMOS RAM */ \ + u8 century; /* Index to century in RTC CMOS RAM */ \ + u16 iapc_boot_arch; /* IA-PC Boot Architecture Flags. See Table 5-10 for description*/ + /* * ACPI 2.0 Fixed ACPI Description Table (FADT) */ struct fadt_descriptor_rev2 { ACPI_TABLE_HEADER_DEF /* ACPI common table header */ - u32 V1_firmware_ctrl; /* 32-bit physical address of FACS */ - u32 V1_dsdt; /* 32-bit physical address of DSDT */ - u8 reserved1; /* System Interrupt Model isn't used in ACPI 2.0*/ - u8 prefer_PM_profile; /* Conveys preferred power management profile to OSPM. */ - u16 sci_int; /* System vector of SCI interrupt */ - u32 smi_cmd; /* Port address of SMI command port */ - u8 acpi_enable; /* Value to write to smi_cmd to enable ACPI */ - u8 acpi_disable; /* Value to write to smi_cmd to disable ACPI */ - u8 S4bios_req; /* Value to write to SMI CMD to enter S4BIOS state */ - u8 pstate_cnt; /* Processor performance state control*/ - u32 V1_pm1a_evt_blk; /* Port address of Power Mgt 1a acpi_event Reg Blk */ - u32 V1_pm1b_evt_blk; /* Port address of Power Mgt 1b acpi_event Reg Blk */ - u32 V1_pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */ - u32 V1_pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */ - u32 V1_pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */ - u32 V1_pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */ - u32 V1_gpe0_blk; /* Port addr of General Purpose acpi_event 0 Reg Blk */ - u32 V1_gpe1_blk; /* Port addr of General Purpose acpi_event 1 Reg Blk */ - u8 pm1_evt_len; /* Byte length of ports at pm1_x_evt_blk */ - u8 pm1_cnt_len; /* Byte length of ports at pm1_x_cnt_blk */ - u8 pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */ - u8 pm_tm_len; /* Byte Length of ports at pm_tm_blk */ - u8 gpe0_blk_len; /* Byte Length of ports at gpe0_blk */ - u8 gpe1_blk_len; /* Byte Length of ports at gpe1_blk */ - u8 gpe1_base; /* Offset in gpe model where gpe1 events start */ - u8 cst_cnt; /* Support for the _CST object and C States change notification.*/ - u16 plvl2_lat; /* Worst case HW latency to enter/exit C2 state */ - u16 plvl3_lat; /* Worst case HW latency to enter/exit C3 state */ - u16 flush_size; /* Number of flush strides that need to be read */ - u16 flush_stride; /* Processor's memory cache line width, in bytes */ - u8 duty_offset; /* Processor's duty cycle index in processor's P_CNT reg*/ - u8 duty_width; /* Processor's duty cycle value bit width in P_CNT register.*/ - u8 day_alrm; /* Index to day-of-month alarm in RTC CMOS RAM */ - u8 mon_alrm; /* Index to month-of-year alarm in RTC CMOS RAM */ - u8 century; /* Index to century in RTC CMOS RAM */ - u16 iapc_boot_arch; /* IA-PC Boot Architecture Flags. See Table 5-10 for description*/ + FADT_REV2_COMMON u8 reserved2; /* Reserved */ u32 wb_invd : 1; /* The wbinvd instruction works properly */ u32 wb_invd_flush : 1; /* The wbinvd flushes but does not invalidate */ @@ -195,6 +199,20 @@ struct fadt_descriptor_rev2 }; +/* "Downrevved" ACPI 2.0 FADT descriptor */ + +struct fadt_descriptor_rev2_minus +{ + ACPI_TABLE_HEADER_DEF /* ACPI common table header */ + FADT_REV2_COMMON + u8 reserved2; /* Reserved */ + u32 flags; + struct acpi_generic_address reset_register; /* Reset register address in GAS format */ + u8 reset_value; /* Value to write to the reset_register port to reset the system. */ + u8 reserved7[3]; /* These three bytes must be zero */ +}; + + /* Embedded Controller */ struct ec_boot_resources diff --git a/xen/include/acpi/actypes.h b/xen/include/acpi/actypes.h index ae1a73e617..51cb780c24 100644 --- a/xen/include/acpi/actypes.h +++ b/xen/include/acpi/actypes.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2004, R. Byron Moore + * Copyright (C) 2000 - 2005, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -303,7 +303,7 @@ struct uint32_struct typedef u32 acpi_integer; #define ACPI_INTEGER_MAX ACPI_UINT32_MAX #define ACPI_INTEGER_BIT_SIZE 32 -#define ACPI_MAX_DECIMAL_DIGITS 10 +#define ACPI_MAX_DECIMAL_DIGITS 10 /* 2^32 = 4,294,967,296 */ #define ACPI_USE_NATIVE_DIVIDE /* Use compiler native 32-bit divide */ @@ -315,13 +315,18 @@ typedef u32 acpi_integer; typedef u64 acpi_integer; #define ACPI_INTEGER_MAX ACPI_UINT64_MAX #define ACPI_INTEGER_BIT_SIZE 64 -#define ACPI_MAX_DECIMAL_DIGITS 19 +#define ACPI_MAX_DECIMAL_DIGITS 20 /* 2^64 = 18,446,744,073,709,551,616 */ + #if ACPI_MACHINE_WIDTH == 64 #define ACPI_USE_NATIVE_DIVIDE /* Use compiler native 64-bit divide */ #endif #endif +#define ACPI_MAX64_DECIMAL_DIGITS 20 +#define ACPI_MAX32_DECIMAL_DIGITS 10 +#define ACPI_MAX16_DECIMAL_DIGITS 5 +#define ACPI_MAX8_DECIMAL_DIGITS 3 /* * Constants with special meanings @@ -349,7 +354,6 @@ typedef u64 acpi_integer; /* * Power state values */ - #define ACPI_STATE_UNKNOWN (u8) 0xFF #define ACPI_STATE_S0 (u8) 0 @@ -393,7 +397,6 @@ typedef u64 acpi_integer; #define ACPI_NOTIFY_BUS_MODE_MISMATCH (u8) 6 #define ACPI_NOTIFY_POWER_FAULT (u8) 7 - /* * Table types. These values are passed to the table related APIs */ @@ -409,14 +412,13 @@ typedef u32 acpi_table_type; #define ACPI_TABLE_MAX 6 #define NUM_ACPI_TABLE_TYPES (ACPI_TABLE_MAX+1) - /* * Types associated with ACPI names and objects. The first group of * values (up to ACPI_TYPE_EXTERNAL_MAX) correspond to the definition * of the ACPI object_type() operator (See the ACPI Spec). Therefore, * only add to the first group if the spec changes. * - * Types must be kept in sync with the global acpi_ns_properties + * NOTE: Types must be kept in sync with the global acpi_ns_properties * and acpi_ns_type_names arrays. */ typedef u32 acpi_object_type; @@ -453,26 +455,27 @@ typedef u32 acpi_object_type; #define ACPI_TYPE_LOCAL_INDEX_FIELD 0x13 #define ACPI_TYPE_LOCAL_REFERENCE 0x14 /* Arg#, Local#, Name, Debug, ref_of, Index */ #define ACPI_TYPE_LOCAL_ALIAS 0x15 -#define ACPI_TYPE_LOCAL_NOTIFY 0x16 -#define ACPI_TYPE_LOCAL_ADDRESS_HANDLER 0x17 -#define ACPI_TYPE_LOCAL_RESOURCE 0x18 -#define ACPI_TYPE_LOCAL_RESOURCE_FIELD 0x19 -#define ACPI_TYPE_LOCAL_SCOPE 0x1A /* 1 Name, multiple object_list Nodes */ +#define ACPI_TYPE_LOCAL_METHOD_ALIAS 0x16 +#define ACPI_TYPE_LOCAL_NOTIFY 0x17 +#define ACPI_TYPE_LOCAL_ADDRESS_HANDLER 0x18 +#define ACPI_TYPE_LOCAL_RESOURCE 0x19 +#define ACPI_TYPE_LOCAL_RESOURCE_FIELD 0x1A +#define ACPI_TYPE_LOCAL_SCOPE 0x1B /* 1 Name, multiple object_list Nodes */ -#define ACPI_TYPE_NS_NODE_MAX 0x1A /* Last typecode used within a NS Node */ +#define ACPI_TYPE_NS_NODE_MAX 0x1B /* Last typecode used within a NS Node */ /* * These are special object types that never appear in * a Namespace node, only in an union acpi_operand_object */ -#define ACPI_TYPE_LOCAL_EXTRA 0x1B -#define ACPI_TYPE_LOCAL_DATA 0x1C +#define ACPI_TYPE_LOCAL_EXTRA 0x1C +#define ACPI_TYPE_LOCAL_DATA 0x1D -#define ACPI_TYPE_LOCAL_MAX 0x1C +#define ACPI_TYPE_LOCAL_MAX 0x1D /* All types above here are invalid */ -#define ACPI_TYPE_INVALID 0x1D +#define ACPI_TYPE_INVALID 0x1E #define ACPI_TYPE_NOT_FOUND 0xFF @@ -514,9 +517,8 @@ typedef u32 acpi_object_type; #define ACPI_WRITE 1 #define ACPI_IO_MASK 1 - /* - * Acpi Event Types: Fixed & General Purpose + * Event Types: Fixed & General Purpose */ typedef u32 acpi_event_type; @@ -531,25 +533,8 @@ typedef u32 acpi_event_type; #define ACPI_EVENT_MAX 4 #define ACPI_NUM_FIXED_EVENTS ACPI_EVENT_MAX + 1 -#define ACPI_GPE_INVALID 0xFF -#define ACPI_GPE_MAX 0xFF -#define ACPI_NUM_GPE 256 - -#define ACPI_EVENT_LEVEL_TRIGGERED 1 -#define ACPI_EVENT_EDGE_TRIGGERED 2 - -/* - * Flags for GPE and Lock interfaces - */ -#define ACPI_EVENT_WAKE_ENABLE 0x2 -#define ACPI_EVENT_WAKE_DISABLE 0x2 - -#define ACPI_NOT_ISR 0x1 -#define ACPI_ISR 0x0 - - /* - * acpi_event Status: + * Event Status - Per event * ------------- * The encoding of acpi_event_status is illustrated below. * Note that a set bit (1) indicates the property is TRUE @@ -570,12 +555,74 @@ typedef u32 acpi_event_status; #define ACPI_EVENT_FLAG_WAKE_ENABLED (acpi_event_status) 0x02 #define ACPI_EVENT_FLAG_SET (acpi_event_status) 0x04 +/* + * General Purpose Events (GPE) + */ +#define ACPI_GPE_INVALID 0xFF +#define ACPI_GPE_MAX 0xFF +#define ACPI_NUM_GPE 256 + +#define ACPI_GPE_ENABLE 0 +#define ACPI_GPE_DISABLE 1 + + +/* + * GPE info flags - Per GPE + * +-+-+-+---+---+-+ + * |7|6|5|4:3|2:1|0| + * +-+-+-+---+---+-+ + * | | | | | | + * | | | | | +--- Interrupt type: Edge or Level Triggered + * | | | | +--- Type: Wake-only, Runtime-only, or wake/runtime + * | | | +--- Type of dispatch -- to method, handler, or none + * | | +--- Enabled for runtime? + * | +--- Enabled for wake? + * +--- System state when GPE ocurred (running/waking) + */ +#define ACPI_GPE_XRUPT_TYPE_MASK (u8) 0x01 +#define ACPI_GPE_LEVEL_TRIGGERED (u8) 0x01 +#define ACPI_GPE_EDGE_TRIGGERED (u8) 0x00 + +#define ACPI_GPE_TYPE_MASK (u8) 0x06 +#define ACPI_GPE_TYPE_WAKE_RUN (u8) 0x06 +#define ACPI_GPE_TYPE_WAKE (u8) 0x02 +#define ACPI_GPE_TYPE_RUNTIME (u8) 0x04 /* Default */ + +#define ACPI_GPE_DISPATCH_MASK (u8) 0x18 +#define ACPI_GPE_DISPATCH_HANDLER (u8) 0x08 +#define ACPI_GPE_DISPATCH_METHOD (u8) 0x10 +#define ACPI_GPE_DISPATCH_NOT_USED (u8) 0x00 /* Default */ + +#define ACPI_GPE_RUN_ENABLE_MASK (u8) 0x20 +#define ACPI_GPE_RUN_ENABLED (u8) 0x20 +#define ACPI_GPE_RUN_DISABLED (u8) 0x00 /* Default */ + +#define ACPI_GPE_WAKE_ENABLE_MASK (u8) 0x40 +#define ACPI_GPE_WAKE_ENABLED (u8) 0x40 +#define ACPI_GPE_WAKE_DISABLED (u8) 0x00 /* Default */ + +#define ACPI_GPE_ENABLE_MASK (u8) 0x60 /* Both run/wake */ + +#define ACPI_GPE_SYSTEM_MASK (u8) 0x80 +#define ACPI_GPE_SYSTEM_RUNNING (u8) 0x80 +#define ACPI_GPE_SYSTEM_WAKING (u8) 0x00 + +/* + * Flags for GPE and Lock interfaces + */ +#define ACPI_EVENT_WAKE_ENABLE 0x2 /* acpi_gpe_enable */ +#define ACPI_EVENT_WAKE_DISABLE 0x2 /* acpi_gpe_disable */ + +#define ACPI_NOT_ISR 0x1 +#define ACPI_ISR 0x0 + /* Notify types */ -#define ACPI_SYSTEM_NOTIFY 0 -#define ACPI_DEVICE_NOTIFY 1 -#define ACPI_MAX_NOTIFY_HANDLER_TYPE 1 +#define ACPI_SYSTEM_NOTIFY 0x1 +#define ACPI_DEVICE_NOTIFY 0x2 +#define ACPI_ALL_NOTIFY 0x3 +#define ACPI_MAX_NOTIFY_HANDLER_TYPE 0x3 #define ACPI_MAX_SYS_NOTIFY 0x7f @@ -756,11 +803,11 @@ struct acpi_system_info */ typedef u32 -(ACPI_SYSTEM_XFACE *OSD_HANDLER) ( +(ACPI_SYSTEM_XFACE *acpi_osd_handler) ( void *context); typedef void -(ACPI_SYSTEM_XFACE *OSD_EXECUTION_CALLBACK) ( +(ACPI_SYSTEM_XFACE *acpi_osd_exec_callback) ( void *context); /* @@ -770,10 +817,6 @@ typedef u32 (*acpi_event_handler) ( void *context); -typedef -void (*acpi_gpe_handler) ( - void *context); - typedef void (*acpi_notify_handler) ( acpi_handle device, @@ -793,8 +836,16 @@ acpi_status (*acpi_init_handler) ( #define ACPI_INIT_DEVICE_INI 1 +typedef +acpi_status (*acpi_exception_handler) ( + acpi_status aml_status, + acpi_name name, + u16 opcode, + u32 aml_offset, + void *context); + -/* Address Spaces (Operation Regions */ +/* Address Spaces (For Operation Regions) */ typedef acpi_status (*acpi_adr_space_handler) ( @@ -861,6 +912,7 @@ struct acpi_compatible_id_list #define ACPI_VALID_HID 0x0004 #define ACPI_VALID_UID 0x0008 #define ACPI_VALID_CID 0x0010 +#define ACPI_VALID_SXDS 0x0020 #define ACPI_COMMON_OBJ_INFO \ @@ -880,11 +932,12 @@ struct acpi_device_info { ACPI_COMMON_OBJ_INFO; - u32 valid; /* Indicates which fields are valid */ + u32 valid; /* Indicates which fields below are valid */ u32 current_status; /* _STA value */ acpi_integer address; /* _ADR value if any */ struct acpi_device_id hardware_id; /* _HID value if any */ struct acpi_device_id unique_id; /* _UID value if any */ + u8 highest_dstates[4]; /* _sx_d values: 0xFF indicates not valid */ struct acpi_compatible_id_list compatibility_id; /* List of _CIDs if any */ }; diff --git a/xen/include/acpi/acutils.h b/xen/include/acpi/acutils.h index 4927d6beab..0de26b8f10 100644 --- a/xen/include/acpi/acutils.h +++ b/xen/include/acpi/acutils.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2004, R. Byron Moore + * Copyright (C) 2000 - 2005, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -52,7 +52,6 @@ acpi_status (*acpi_pkg_callback) ( union acpi_generic_state *state, void *context); - acpi_status acpi_ut_walk_package_tree ( union acpi_operand_object *source_object, @@ -60,7 +59,6 @@ acpi_ut_walk_package_tree ( acpi_pkg_callback walk_callback, void *context); - struct acpi_pkg_info { u8 *free_space; @@ -179,6 +177,12 @@ acpi_ut_strncpy ( const char *src_string, acpi_size count); +int +acpi_ut_memcmp ( + const char *buffer1, + const char *buffer2, + acpi_size count); + int acpi_ut_strncmp ( const char *string1, @@ -473,8 +477,13 @@ acpi_ut_delete_internal_object_list ( #define METHOD_NAME__PRT "_PRT" #define METHOD_NAME__CRS "_CRS" #define METHOD_NAME__PRS "_PRS" +#define METHOD_NAME__PRW "_PRW" +acpi_status +acpi_ut_osi_implementation ( + struct acpi_walk_state *walk_state); + acpi_status acpi_ut_evaluate_object ( struct acpi_namespace_node *prefix_node, @@ -508,6 +517,10 @@ acpi_ut_execute_UID ( struct acpi_namespace_node *device_node, struct acpi_device_id *uid); +acpi_status +acpi_ut_execute_sxds ( + struct acpi_namespace_node *device_node, + u8 *highest); /* * ut_mutex - mutual exclusion interfaces @@ -570,6 +583,10 @@ union acpi_operand_object * acpi_ut_create_buffer_object ( acpi_size buffer_size); +union acpi_operand_object * +acpi_ut_create_string_object ( + acpi_size string_size); + /* * ut_ref_cnt - Object reference count management @@ -649,12 +666,14 @@ acpi_ut_create_update_state_and_push ( u16 action, union acpi_generic_state **state_list); +#ifdef ACPI_FUTURE_USAGE acpi_status acpi_ut_create_pkg_state_and_push ( void *internal_object, void *external_object, u16 index, union acpi_generic_state **state_list); +#endif union acpi_generic_state * acpi_ut_create_control_state ( @@ -664,6 +683,7 @@ void acpi_ut_delete_generic_state ( union acpi_generic_state *state); +#ifdef ACPI_ENABLE_OBJECT_CACHE void acpi_ut_delete_generic_state_cache ( void); @@ -671,6 +691,7 @@ acpi_ut_delete_generic_state_cache ( void acpi_ut_delete_object_cache ( void); +#endif /* * utmisc @@ -683,14 +704,14 @@ acpi_ut_print_string ( acpi_status acpi_ut_divide ( - acpi_integer *in_dividend, - acpi_integer *in_divisor, + acpi_integer in_dividend, + acpi_integer in_divisor, acpi_integer *out_quotient, acpi_integer *out_remainder); acpi_status acpi_ut_short_divide ( - acpi_integer *in_dividend, + acpi_integer in_dividend, u32 divisor, acpi_integer *out_quotient, u32 *out_remainder); @@ -709,9 +730,15 @@ acpi_ut_strtoul64 ( u32 base, acpi_integer *ret_integer); +/* Values for Base above (16=Hex, 10=Decimal) */ + +#define ACPI_ANY_BASE 0 + +#ifdef ACPI_FUTURE_USAGE char * acpi_ut_strupr ( char *src_string); +#endif u8 * acpi_ut_get_resource_end_tag ( @@ -753,9 +780,11 @@ acpi_ut_release_to_cache ( u32 list_id, void *object); +#ifdef ACPI_ENABLE_OBJECT_CACHE void acpi_ut_delete_generic_cache ( u32 list_id); +#endif acpi_status acpi_ut_validate_buffer ( @@ -830,9 +859,11 @@ acpi_ut_remove_allocation ( char *module, u32 line); +#ifdef ACPI_FUTURE_USAGE void acpi_ut_dump_allocation_info ( void); +#endif void acpi_ut_dump_allocations ( diff --git a/xen/include/acpi/platform/acenv.h b/xen/include/acpi/platform/acenv.h index 9a0cd41084..5a956b549b 100644 --- a/xen/include/acpi/platform/acenv.h +++ b/xen/include/acpi/platform/acenv.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2004, R. Byron Moore + * Copyright (C) 2000 - 2005, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -57,6 +57,7 @@ #define ACPI_DISASSEMBLER #define ACPI_NO_METHOD_EXECUTION #define ACPI_USE_SYSTEM_CLIBRARY +#define ACPI_ENABLE_OBJECT_CACHE #endif #ifdef _ACPI_EXEC_APP @@ -67,6 +68,7 @@ #define ACPI_DEBUGGER #define ACPI_DISASSEMBLER #define ACPI_USE_SYSTEM_CLIBRARY +#define ACPI_ENABLE_OBJECT_CACHE #endif #ifdef _ACPI_ASL_COMPILER @@ -75,6 +77,7 @@ #define ACPI_DISASSEMBLER #define ACPI_CONSTANT_EVAL_ONLY #define ACPI_USE_SYSTEM_CLIBRARY +#define ACPI_ENABLE_OBJECT_CACHE #endif /* @@ -152,12 +155,8 @@ #define COMPILER_DEPENDENT_INT64 long long #define COMPILER_DEPENDENT_UINT64 unsigned long long - -/* Name of host operating system (returned by the _OS_ namespace object) */ - -#define ACPI_OS_NAME "Intel ACPI/CA Core Subsystem" - -/* This macro is used to tag functions as "printf-like" because +/* + * This macro is used to tag functions as "printf-like" because * some compilers can catch printf format string problems. MSVC * doesn't, so this is proprocessed away. */ @@ -227,7 +226,11 @@ */ #define ACPI_STRSTR(s1,s2) strstr((s1), (s2)) + +#ifdef ACPI_FUTURE_USAGE #define ACPI_STRUPR(s) (void) acpi_ut_strupr ((s)) +#endif + #define ACPI_STRLEN(s) (acpi_size) strlen((s)) #define ACPI_STRCPY(d,s) (void) strcpy((d), (s)) #define ACPI_STRNCPY(d,s,n) (void) strncpy((d), (s), (acpi_size)(n)) @@ -236,6 +239,7 @@ #define ACPI_STRCAT(d,s) (void) strcat((d), (s)) #define ACPI_STRNCAT(d,s,n) strncat((d), (s), (acpi_size)(n)) #define ACPI_STRTOUL(d,s,n) strtoul((d), (s), (acpi_size)(n)) +#define ACPI_MEMCMP(s1,s2,n) memcmp((s1), (s2), (acpi_size)(n)) #define ACPI_MEMCPY(d,s,n) (void) memcpy((d), (s), (acpi_size)(n)) #define ACPI_MEMSET(d,s,n) (void) memset((d), (s), (acpi_size)(n)) @@ -290,7 +294,11 @@ typedef char *va_list; #define ACPI_STRSTR(s1,s2) acpi_ut_strstr ((s1), (s2)) + +#ifdef ACPI_FUTURE_USAGE #define ACPI_STRUPR(s) (void) acpi_ut_strupr ((s)) +#endif + #define ACPI_STRLEN(s) (acpi_size) acpi_ut_strlen ((s)) #define ACPI_STRCPY(d,s) (void) acpi_ut_strcpy ((d), (s)) #define ACPI_STRNCPY(d,s,n) (void) acpi_ut_strncpy ((d), (s), (acpi_size)(n)) @@ -299,6 +307,7 @@ typedef char *va_list; #define ACPI_STRCAT(d,s) (void) acpi_ut_strcat ((d), (s)) #define ACPI_STRNCAT(d,s,n) acpi_ut_strncat ((d), (s), (acpi_size)(n)) #define ACPI_STRTOUL(d,s,n) acpi_ut_strtoul ((d), (s), (acpi_size)(n)) +#define ACPI_MEMCMP(s1,s2,n) acpi_ut_memcmp((s1), (s2), (acpi_size)(n)) #define ACPI_MEMCPY(d,s,n) (void) acpi_ut_memcpy ((d), (s), (acpi_size)(n)) #define ACPI_MEMSET(d,v,n) (void) acpi_ut_memset ((d), (v), (acpi_size)(n)) #define ACPI_TOUPPER acpi_ut_to_upper diff --git a/xen/include/acpi/platform/acgcc.h b/xen/include/acpi/platform/acgcc.h index ac15b08460..91fda36b04 100644 --- a/xen/include/acpi/platform/acgcc.h +++ b/xen/include/acpi/platform/acgcc.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2004, R. Byron Moore + * Copyright (C) 2000 - 2005, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -54,6 +54,6 @@ * to to tell the compiler warning in a per-variable manner that a variable * is unused. */ -#define ACPI_UNUSED_VAR __attribute_used__ +#define ACPI_UNUSED_VAR __attribute__ ((unused)) #endif /* __ACGCC_H__ */ diff --git a/xen/include/acpi/platform/aclinux.h b/xen/include/acpi/platform/aclinux.h index eecd6c888c..4006b0ce01 100644 --- a/xen/include/acpi/platform/aclinux.h +++ b/xen/include/acpi/platform/aclinux.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2004, R. Byron Moore + * Copyright (C) 2000 - 2005, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,8 +44,6 @@ #ifndef __ACLINUX_H__ #define __ACLINUX_H__ -#define ACPI_OS_NAME "Linux" - #define ACPI_USE_SYSTEM_CLIBRARY #define ACPI_USE_DO_WHILE_0 @@ -83,6 +81,8 @@ #define ACPI_USE_NATIVE_DIVIDE #endif +#define __cdecl +#define ACPI_FLUSH_CPU_CACHE() #endif /* __KERNEL__ */ /* Linux uses GCC */ diff --git a/xen/include/asm-ia64/config.h b/xen/include/asm-ia64/config.h index 74dbb3a4e5..27f1e43620 100644 --- a/xen/include/asm-ia64/config.h +++ b/xen/include/asm-ia64/config.h @@ -31,10 +31,6 @@ typedef int pid_t; #define touch_nmi_watchdog() // from linux/include/linux/types.h -#define BITS_TO_LONGS(bits) \ - (((bits)+BITS_PER_LONG-1)/BITS_PER_LONG) -#define DECLARE_BITMAP(name,bits) \ - unsigned long name[BITS_TO_LONGS(bits)] #define CLEAR_BITMAP(name,bits) \ memset(name, 0, BITS_TO_LONGS(bits)*sizeof(unsigned long)) @@ -57,7 +53,6 @@ extern char _end[]; /* standard ELF symbol */ //#define __kernel //#define __safe #define __force -#define __iomem #define __chk_user_ptr(x) (void)0 //#define __chk_io_ptr(x) (void)0 //#define __builtin_warning(x, y...) (1) @@ -77,9 +72,6 @@ extern char _end[]; /* standard ELF symbol */ //#define CONFIG_NR_CPUS 16 #define barrier() __asm__ __volatile__("": : :"memory") -// linux/include/spinlock.h -#define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED - /////////////////////////////////////////////////////////////// // xen/include/asm/config.h // Natural boundary upon TR size to define xenheap space diff --git a/xen/include/asm-x86/apic.h b/xen/include/asm-x86/apic.h index 61d3f8fe47..73112359a5 100644 --- a/xen/include/asm-x86/apic.h +++ b/xen/include/asm-x86/apic.h @@ -2,19 +2,34 @@ #define __ASM_APIC_H #include -#include +#include #include #include -#ifdef CONFIG_X86_LOCAL_APIC +#define Dprintk(x...) + +/* + * Debugging macros + */ +#define APIC_QUIET 0 +#define APIC_VERBOSE 1 +#define APIC_DEBUG 2 -#define APIC_DEBUG 0 +extern int apic_verbosity; -#if APIC_DEBUG -#define Dprintk(x...) printk(x) -#else -#define Dprintk(x...) -#endif +/* + * Define the default level of output to be very little + * This can be turned up by using apic=verbose for more + * information and apic=debug for _lots_ of information. + * apic_verbosity is defined in apic.c + */ +#define apic_printk(v, s, a...) do { \ + if ((v) <= apic_verbosity) \ + printk(s, ##a); \ + } while (0) + + +#ifdef CONFIG_X86_LOCAL_APIC /* * Basic functions accessing APICs. @@ -37,9 +52,12 @@ static __inline u32 apic_read(unsigned long reg) static __inline__ void apic_wait_icr_idle(void) { - do { } while ( apic_read( APIC_ICR ) & APIC_ICR_BUSY ); + while ( apic_read( APIC_ICR ) & APIC_ICR_BUSY ) + cpu_relax(); } +int get_physical_broadcast(void); + #ifdef CONFIG_X86_GOOD_APIC # define FORCE_READ_AROUND_WRITE 0 # define apic_read_around(x) @@ -63,21 +81,29 @@ static inline void ack_APIC_irq(void) apic_write_around(APIC_EOI, 0); } +extern void (*wait_timer_tick)(void); + extern int get_maxlvt(void); extern void clear_local_APIC(void); extern void connect_bsp_APIC (void); extern void disconnect_bsp_APIC (void); extern void disable_local_APIC (void); +extern void lapic_shutdown (void); extern int verify_local_APIC (void); extern void cache_APIC_registers (void); extern void sync_Arb_IDs (void); extern void init_bsp_APIC (void); extern void setup_local_APIC (void); extern void init_apic_mappings (void); -extern void smp_local_timer_interrupt (struct cpu_user_regs * regs); -extern void setup_APIC_clocks (void); +extern void smp_local_timer_interrupt (struct cpu_user_regs *regs); +extern void setup_boot_APIC_clock (void); +extern void setup_secondary_APIC_clock (void); extern void setup_apic_nmi_watchdog (void); -extern void nmi_watchdog_tick (struct cpu_user_regs * regs); +extern int reserve_lapic_nmi(void); +extern void release_lapic_nmi(void); +extern void disable_timer_nmi_watchdog(void); +extern void enable_timer_nmi_watchdog(void); +extern void nmi_watchdog_tick (struct cpu_user_regs *regs); extern void touch_nmi_watchdog(void); extern int APIC_init_uniprocessor (void); extern void disable_APIC_timer(void); @@ -85,6 +111,7 @@ extern void enable_APIC_timer(void); extern unsigned int watchdog_on; extern int check_nmi_watchdog (void); +extern void enable_NMI_through_LVT0 (void * dummy); extern unsigned int nmi_watchdog; #define NMI_NONE 0 @@ -92,6 +119,9 @@ extern unsigned int nmi_watchdog; #define NMI_LOCAL_APIC 2 #define NMI_INVALID 3 -#endif /* CONFIG_X86_LOCAL_APIC */ +#else /* !CONFIG_X86_LOCAL_APIC */ +static inline void lapic_shutdown(void) { } + +#endif /* !CONFIG_X86_LOCAL_APIC */ #endif /* __ASM_APIC_H */ diff --git a/xen/include/asm-x86/apicdef.h b/xen/include/asm-x86/apicdef.h index 8d7f3aa3d7..911a55ef82 100644 --- a/xen/include/asm-x86/apicdef.h +++ b/xen/include/asm-x86/apicdef.h @@ -11,14 +11,11 @@ #define APIC_DEFAULT_PHYS_BASE 0xfee00000 #define APIC_ID 0x20 -#define APIC_ID_MASK (0x0F<<24) -#define GET_APIC_ID(x) (((x)>>24)&0x0F) #define APIC_LVR 0x30 #define APIC_LVR_MASK 0xFF00FF #define GET_APIC_VERSION(x) ((x)&0xFF) #define GET_APIC_MAXLVT(x) (((x)>>16)&0xFF) #define APIC_INTEGRATED(x) ((x)&0xF0) -#define APIC_XAPIC_SUPPORT(x) ((x)>=0x14) #define APIC_TASKPRI 0x80 #define APIC_TPRI_MASK 0xFF #define APIC_ARBPRI 0x90 @@ -33,8 +30,8 @@ #define SET_APIC_LOGICAL_ID(x) (((x)<<24)) #define APIC_ALL_CPUS 0xFF #define APIC_DFR 0xE0 -#define APIC_DFR_CLUSTER 0x0FFFFFFFul /* Clustered */ -#define APIC_DFR_FLAT 0xFFFFFFFFul /* Flat mode */ +#define APIC_DFR_CLUSTER 0x0FFFFFFFul +#define APIC_DFR_FLAT 0xFFFFFFFFul #define APIC_SPIV 0xF0 #define APIC_SPIV_FOCUS_DISABLED (1<<9) #define APIC_SPIV_APIC_ENABLED (1<<8) @@ -60,7 +57,6 @@ #define APIC_INT_LEVELTRIG 0x08000 #define APIC_INT_ASSERT 0x04000 #define APIC_ICR_BUSY 0x01000 -#define APIC_DEST_PHYSICAL 0x00000 #define APIC_DEST_LOGICAL 0x00800 #define APIC_DM_FIXED 0x00000 #define APIC_DM_LOWEST 0x00100 @@ -75,6 +71,7 @@ #define GET_APIC_DEST_FIELD(x) (((x)>>24)&0xFF) #define SET_APIC_DEST_FIELD(x) ((x)<<24) #define APIC_LVTT 0x320 +#define APIC_LVTTHMR 0x330 #define APIC_LVTPC 0x340 #define APIC_LVT0 0x350 #define APIC_LVT_TIMER_BASE_MASK (0x3<<18) @@ -111,18 +108,272 @@ #define APIC_BASE (fix_to_virt(FIX_APIC_BASE)) -#ifdef CONFIG_X86_CLUSTERED_APIC -#define MAX_IO_APICS 32 +#ifdef CONFIG_NUMA + #define MAX_IO_APICS 32 #else -#define MAX_IO_APICS 8 + #define MAX_IO_APICS 8 #endif - /* - * The broadcast ID is 0xF for old APICs and 0xFF for xAPICs. SAPICs - * don't broadcast (yet?), but if they did, they might use 0xFFFF. + * the local APIC register structure, memory mapped. Not terribly well + * tested, but we might eventually use this one in the future - the + * problem why we cannot use it right now is the P5 APIC, it has an + * errata which cannot take 8-bit reads and writes, only 32-bit ones ... */ -#define APIC_BROADCAST_ID_XAPIC (0xFF) -#define APIC_BROADCAST_ID_APIC (0x0F) +#define u32 unsigned int + +#define lapic ((volatile struct local_apic *)APIC_BASE) + +#ifndef __ASSEMBLY__ +struct local_apic { + +/*000*/ struct { u32 __reserved[4]; } __reserved_01; + +/*010*/ struct { u32 __reserved[4]; } __reserved_02; + +/*020*/ struct { /* APIC ID Register */ + u32 __reserved_1 : 24, + phys_apic_id : 4, + __reserved_2 : 4; + u32 __reserved[3]; + } id; + +/*030*/ const + struct { /* APIC Version Register */ + u32 version : 8, + __reserved_1 : 8, + max_lvt : 8, + __reserved_2 : 8; + u32 __reserved[3]; + } version; + +/*040*/ struct { u32 __reserved[4]; } __reserved_03; + +/*050*/ struct { u32 __reserved[4]; } __reserved_04; + +/*060*/ struct { u32 __reserved[4]; } __reserved_05; + +/*070*/ struct { u32 __reserved[4]; } __reserved_06; + +/*080*/ struct { /* Task Priority Register */ + u32 priority : 8, + __reserved_1 : 24; + u32 __reserved_2[3]; + } tpr; + +/*090*/ const + struct { /* Arbitration Priority Register */ + u32 priority : 8, + __reserved_1 : 24; + u32 __reserved_2[3]; + } apr; + +/*0A0*/ const + struct { /* Processor Priority Register */ + u32 priority : 8, + __reserved_1 : 24; + u32 __reserved_2[3]; + } ppr; + +/*0B0*/ struct { /* End Of Interrupt Register */ + u32 eoi; + u32 __reserved[3]; + } eoi; + +/*0C0*/ struct { u32 __reserved[4]; } __reserved_07; + +/*0D0*/ struct { /* Logical Destination Register */ + u32 __reserved_1 : 24, + logical_dest : 8; + u32 __reserved_2[3]; + } ldr; + +/*0E0*/ struct { /* Destination Format Register */ + u32 __reserved_1 : 28, + model : 4; + u32 __reserved_2[3]; + } dfr; + +/*0F0*/ struct { /* Spurious Interrupt Vector Register */ + u32 spurious_vector : 8, + apic_enabled : 1, + focus_cpu : 1, + __reserved_2 : 22; + u32 __reserved_3[3]; + } svr; + +/*100*/ struct { /* In Service Register */ +/*170*/ u32 bitfield; + u32 __reserved[3]; + } isr [8]; + +/*180*/ struct { /* Trigger Mode Register */ +/*1F0*/ u32 bitfield; + u32 __reserved[3]; + } tmr [8]; + +/*200*/ struct { /* Interrupt Request Register */ +/*270*/ u32 bitfield; + u32 __reserved[3]; + } irr [8]; + +/*280*/ union { /* Error Status Register */ + struct { + u32 send_cs_error : 1, + receive_cs_error : 1, + send_accept_error : 1, + receive_accept_error : 1, + __reserved_1 : 1, + send_illegal_vector : 1, + receive_illegal_vector : 1, + illegal_register_address : 1, + __reserved_2 : 24; + u32 __reserved_3[3]; + } error_bits; + struct { + u32 errors; + u32 __reserved_3[3]; + } all_errors; + } esr; + +/*290*/ struct { u32 __reserved[4]; } __reserved_08; + +/*2A0*/ struct { u32 __reserved[4]; } __reserved_09; + +/*2B0*/ struct { u32 __reserved[4]; } __reserved_10; + +/*2C0*/ struct { u32 __reserved[4]; } __reserved_11; + +/*2D0*/ struct { u32 __reserved[4]; } __reserved_12; + +/*2E0*/ struct { u32 __reserved[4]; } __reserved_13; + +/*2F0*/ struct { u32 __reserved[4]; } __reserved_14; + +/*300*/ struct { /* Interrupt Command Register 1 */ + u32 vector : 8, + delivery_mode : 3, + destination_mode : 1, + delivery_status : 1, + __reserved_1 : 1, + level : 1, + trigger : 1, + __reserved_2 : 2, + shorthand : 2, + __reserved_3 : 12; + u32 __reserved_4[3]; + } icr1; + +/*310*/ struct { /* Interrupt Command Register 2 */ + union { + u32 __reserved_1 : 24, + phys_dest : 4, + __reserved_2 : 4; + u32 __reserved_3 : 24, + logical_dest : 8; + } dest; + u32 __reserved_4[3]; + } icr2; + +/*320*/ struct { /* LVT - Timer */ + u32 vector : 8, + __reserved_1 : 4, + delivery_status : 1, + __reserved_2 : 3, + mask : 1, + timer_mode : 1, + __reserved_3 : 14; + u32 __reserved_4[3]; + } lvt_timer; + +/*330*/ struct { /* LVT - Thermal Sensor */ + u32 vector : 8, + delivery_mode : 3, + __reserved_1 : 1, + delivery_status : 1, + __reserved_2 : 3, + mask : 1, + __reserved_3 : 15; + u32 __reserved_4[3]; + } lvt_thermal; + +/*340*/ struct { /* LVT - Performance Counter */ + u32 vector : 8, + delivery_mode : 3, + __reserved_1 : 1, + delivery_status : 1, + __reserved_2 : 3, + mask : 1, + __reserved_3 : 15; + u32 __reserved_4[3]; + } lvt_pc; + +/*350*/ struct { /* LVT - LINT0 */ + u32 vector : 8, + delivery_mode : 3, + __reserved_1 : 1, + delivery_status : 1, + polarity : 1, + remote_irr : 1, + trigger : 1, + mask : 1, + __reserved_2 : 15; + u32 __reserved_3[3]; + } lvt_lint0; + +/*360*/ struct { /* LVT - LINT1 */ + u32 vector : 8, + delivery_mode : 3, + __reserved_1 : 1, + delivery_status : 1, + polarity : 1, + remote_irr : 1, + trigger : 1, + mask : 1, + __reserved_2 : 15; + u32 __reserved_3[3]; + } lvt_lint1; + +/*370*/ struct { /* LVT - Error */ + u32 vector : 8, + __reserved_1 : 4, + delivery_status : 1, + __reserved_2 : 3, + mask : 1, + __reserved_3 : 15; + u32 __reserved_4[3]; + } lvt_error; + +/*380*/ struct { /* Timer Initial Count Register */ + u32 initial_count; + u32 __reserved_2[3]; + } timer_icr; + +/*390*/ const + struct { /* Timer Current Count Register */ + u32 curr_count; + u32 __reserved_2[3]; + } timer_ccr; + +/*3A0*/ struct { u32 __reserved[4]; } __reserved_16; + +/*3B0*/ struct { u32 __reserved[4]; } __reserved_17; + +/*3C0*/ struct { u32 __reserved[4]; } __reserved_18; + +/*3D0*/ struct { u32 __reserved[4]; } __reserved_19; + +/*3E0*/ struct { /* Timer Divide Configuration Register */ + u32 divisor : 4, + __reserved_1 : 28; + u32 __reserved_2[3]; + } timer_dcr; + +/*3F0*/ struct { u32 __reserved[4]; } __reserved_20; + +} __attribute__ ((packed)); +#endif /* !__ASSEMBLY__ */ + +#undef u32 #endif diff --git a/xen/include/asm-x86/config.h b/xen/include/asm-x86/config.h index 7f44c5ae87..1ddc8228db 100644 --- a/xen/include/asm-x86/config.h +++ b/xen/include/asm-x86/config.h @@ -69,6 +69,8 @@ extern unsigned long _end; /* standard ELF symbol */ #if defined(__x86_64__) +#define CONFIG_X86_64 1 + #define asmlinkage #define XENHEAP_DEFAULT_MB (16) @@ -179,6 +181,8 @@ extern unsigned long _end; /* standard ELF symbol */ #elif defined(__i386__) +#define CONFIG_X86_32 1 + #define asmlinkage __attribute__((regparm(0))) /* diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h index 514ccdf0f1..683ba2ac0c 100644 --- a/xen/include/asm-x86/domain.h +++ b/xen/include/asm-x86/domain.h @@ -2,7 +2,9 @@ #ifndef __ASM_DOMAIN_H__ #define __ASM_DOMAIN_H__ +#include #include +#include struct trap_bounce { unsigned long error_code; diff --git a/xen/include/asm-x86/fixmap.h b/xen/include/asm-x86/fixmap.h index e123cb791a..d2d8ef183e 100644 --- a/xen/include/asm-x86/fixmap.h +++ b/xen/include/asm-x86/fixmap.h @@ -13,6 +13,7 @@ #define _ASM_FIXMAP_H #include +#include #include #include #include @@ -52,6 +53,36 @@ extern void __set_fixmap( #define set_fixmap_nocache(idx, phys) \ __set_fixmap(idx, phys, PAGE_HYPERVISOR_NOCACHE) -#define fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT)) +#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT)) +#define __virt_to_fix(x) ((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT) + +extern void __this_fixmap_does_not_exist(void); + +/* + * 'index to address' translation. If anyone tries to use the idx + * directly without translation, we catch the bug with a NULL-deference + * kernel oops. Illegal ranges of incoming indices are caught too. + */ +static always_inline unsigned long fix_to_virt(const unsigned int idx) +{ + /* + * This branch gets completely eliminated after inlining, except when + * someone tries to use fixaddr indices in an illegal way (such as mixing + * up address types or using out-of-range indices). + * + * If it doesn't get removed, the linker will complain loudly with a + * reasonably clear error message. + */ + if (idx >= __end_of_fixed_addresses) + __this_fixmap_does_not_exist(); + + return __fix_to_virt(idx); +} + +static inline unsigned long virt_to_fix(const unsigned long vaddr) +{ + BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START); + return __virt_to_fix(vaddr); +} #endif diff --git a/xen/include/asm-x86/io_apic.h b/xen/include/asm-x86/io_apic.h index 1cc4e557a6..5c71c08f58 100644 --- a/xen/include/asm-x86/io_apic.h +++ b/xen/include/asm-x86/io_apic.h @@ -2,7 +2,8 @@ #define __ASM_IO_APIC_H #include -#include +#include +#include #include /* @@ -13,42 +14,91 @@ #ifdef CONFIG_X86_IO_APIC -#define APIC_MISMATCH_DEBUG +#ifdef CONFIG_PCI_MSI +static inline int use_pci_vector(void) {return 1;} +static inline void disable_edge_ioapic_vector(unsigned int vector) { } +static inline void mask_and_ack_level_ioapic_vector(unsigned int vector) { } +static inline void end_edge_ioapic_vector (unsigned int vector) { } +#define startup_level_ioapic startup_level_ioapic_vector +#define shutdown_level_ioapic mask_IO_APIC_vector +#define enable_level_ioapic unmask_IO_APIC_vector +#define disable_level_ioapic mask_IO_APIC_vector +#define mask_and_ack_level_ioapic mask_and_ack_level_ioapic_vector +#define end_level_ioapic end_level_ioapic_vector +#define set_ioapic_affinity set_ioapic_affinity_vector + +#define startup_edge_ioapic startup_edge_ioapic_vector +#define shutdown_edge_ioapic disable_edge_ioapic_vector +#define enable_edge_ioapic unmask_IO_APIC_vector +#define disable_edge_ioapic disable_edge_ioapic_vector +#define ack_edge_ioapic ack_edge_ioapic_vector +#define end_edge_ioapic end_edge_ioapic_vector +#else +static inline int use_pci_vector(void) {return 0;} +static inline void disable_edge_ioapic_irq(unsigned int irq) { } +static inline void mask_and_ack_level_ioapic_irq(unsigned int irq) { } +static inline void end_edge_ioapic_irq (unsigned int irq) { } +#define startup_level_ioapic startup_level_ioapic_irq +#define shutdown_level_ioapic mask_IO_APIC_irq +#define enable_level_ioapic unmask_IO_APIC_irq +#define disable_level_ioapic mask_IO_APIC_irq +#define mask_and_ack_level_ioapic mask_and_ack_level_ioapic_irq +#define end_level_ioapic end_level_ioapic_irq +#define set_ioapic_affinity set_ioapic_affinity_irq + +#define startup_edge_ioapic startup_edge_ioapic_irq +#define shutdown_edge_ioapic disable_edge_ioapic_irq +#define enable_edge_ioapic unmask_IO_APIC_irq +#define disable_edge_ioapic disable_edge_ioapic_irq +#define ack_edge_ioapic ack_edge_ioapic_irq +#define end_edge_ioapic end_edge_ioapic_irq +#endif #define IO_APIC_BASE(idx) \ - ((volatile int *)(fix_to_virt(FIX_IO_APIC_BASE_0 + idx) \ + ((volatile int *)(__fix_to_virt(FIX_IO_APIC_BASE_0 + idx) \ + (mp_ioapics[idx].mpc_apicaddr & ~PAGE_MASK))) /* * The structure of the IO-APIC: */ -struct IO_APIC_reg_00 { - __u32 __reserved_2 : 14, - LTS : 1, - delivery_type : 1, - __reserved_1 : 8, - ID : 4, - __reserved_0 : 4; -} __attribute__ ((packed)); +union IO_APIC_reg_00 { + u32 raw; + struct { + u32 __reserved_2 : 14, + LTS : 1, + delivery_type : 1, + __reserved_1 : 8, + ID : 8; + } __attribute__ ((packed)) bits; +}; -struct IO_APIC_reg_01 { - __u32 version : 8, - __reserved_2 : 7, - PRQ : 1, - entries : 8, - __reserved_1 : 8; -} __attribute__ ((packed)); +union IO_APIC_reg_01 { + u32 raw; + struct { + u32 version : 8, + __reserved_2 : 7, + PRQ : 1, + entries : 8, + __reserved_1 : 8; + } __attribute__ ((packed)) bits; +}; -struct IO_APIC_reg_02 { - __u32 __reserved_2 : 24, - arbitration : 4, - __reserved_1 : 4; -} __attribute__ ((packed)); +union IO_APIC_reg_02 { + u32 raw; + struct { + u32 __reserved_2 : 24, + arbitration : 4, + __reserved_1 : 4; + } __attribute__ ((packed)) bits; +}; -struct IO_APIC_reg_03 { - __u32 boot_DT : 1, - __reserved_1 : 31; -} __attribute__ ((packed)); +union IO_APIC_reg_03 { + u32 raw; + struct { + u32 boot_DT : 1, + __reserved_1 : 31; + } __attribute__ ((packed)) bits; +}; /* * # of IO-APICs and # of IRQ routing registers @@ -106,7 +156,7 @@ extern struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS]; extern int mp_irq_entries; /* MP IRQ source entries */ -extern struct mpc_config_intsrc *mp_irqs; +extern struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES]; /* non-0 if default (table-less) MP configuration */ extern int mpc_default_type; @@ -124,47 +174,41 @@ static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned i } /* - * Synchronize the IO-APIC and the CPU by doing - * a dummy read from the IO-APIC + * Re-write a value: to be used for read-modify-write + * cycles where the read already set up the index register. + * + * Older SiS APIC requires we rewrite the index regiser */ -static inline void io_apic_sync(unsigned int apic) +#define sis_apic_bug 0 /* This may need propagating from domain0. */ +static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value) { - (void) *(IO_APIC_BASE(apic)+4); + if (sis_apic_bug) + *IO_APIC_BASE(apic) = reg; + *(IO_APIC_BASE(apic)+4) = value; } +/* 1 if "noapic" boot option passed */ +extern int skip_ioapic_setup; + /* * If we use the IO-APIC for IRQ routing, disable automatic * assignment of PCI IRQ's. */ -#define io_apic_assign_pci_irqs (mp_irq_entries && !skip_ioapic_setup) +#define io_apic_assign_pci_irqs (mp_irq_entries && !skip_ioapic_setup && io_apic_irqs) #ifdef CONFIG_ACPI_BOOT extern int io_apic_get_unique_id (int ioapic, int apic_id); extern int io_apic_get_version (int ioapic); extern int io_apic_get_redir_entries (int ioapic); extern int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int active_high_low); -#endif - -extern int skip_ioapic_setup; /* 1 for "noapic" */ - -static inline void disable_ioapic_setup(void) -{ - skip_ioapic_setup = 1; -} - -static inline int ioapic_setup_disabled(void) -{ - return skip_ioapic_setup; -} +#endif /*CONFIG_ACPI_BOOT*/ -extern int assign_irq_vector(int irq); +extern int (*ioapic_renumber_irq)(int ioapic, int irq); -#else /* !CONFIG_X86_IO_APIC */ +#else /* !CONFIG_X86_IO_APIC */ #define io_apic_assign_pci_irqs 0 +#endif -static inline void disable_ioapic_setup(void) -{ } - -#endif /* !CONFIG_X86_IO_APIC */ +extern int assign_irq_vector(int irq); #endif diff --git a/xen/include/asm-x86/io_ports.h b/xen/include/asm-x86/io_ports.h deleted file mode 100644 index db490bd142..0000000000 --- a/xen/include/asm-x86/io_ports.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * based on linux-2.6.10/include/asm-i386/mach-default/io_ports.h - * - * Machine specific IO port address definition for generic. - * Written by Osamu Tomita - */ -#ifndef _MACH_IO_PORTS_H -#define _MACH_IO_PORTS_H - -/* i8253A PIT registers */ -#define PIT_MODE 0x43 -#define PIT_CH0 0x40 -#define PIT_CH2 0x42 - -/* i8259A PIC registers */ -#define PIC_MASTER_CMD 0x20 -#define PIC_MASTER_IMR 0x21 -#define PIC_MASTER_ISR PIC_MASTER_CMD -#define PIC_MASTER_POLL PIC_MASTER_ISR -#define PIC_MASTER_OCW3 PIC_MASTER_ISR -#define PIC_SLAVE_CMD 0xa0 -#define PIC_SLAVE_IMR 0xa1 - -/* i8259A PIC related value */ -#define PIC_CASCADE_IR 2 -#define MASTER_ICW4_DEFAULT 0x01 -#define SLAVE_ICW4_DEFAULT 0x01 -#define PIC_ICW4_AEOI 2 - -#endif /* !_MACH_IO_PORTS_H */ diff --git a/xen/include/asm-x86/irq.h b/xen/include/asm-x86/irq.h index bc7ecfa317..1a38b524a6 100644 --- a/xen/include/asm-x86/irq.h +++ b/xen/include/asm-x86/irq.h @@ -6,59 +6,19 @@ #include #include #include +#include extern void disable_irq(unsigned int); extern void disable_irq_nosync(unsigned int); extern void enable_irq(unsigned int); -/* - * IDT vectors usable for external interrupt sources start - * at 0x20: - */ -#define FIRST_EXTERNAL_VECTOR 0x30 - -#define NR_IRQS (256 - FIRST_EXTERNAL_VECTOR) - -#define HYPERCALL_VECTOR 0x82 - -/* - * Vectors 0x30-0x3f are used for ISA interrupts. - */ - -/* - * Special IRQ vectors used by the SMP architecture, 0xf0-0xff - */ -#define SPURIOUS_APIC_VECTOR 0xff -#define ERROR_APIC_VECTOR 0xfe -#define INVALIDATE_TLB_VECTOR 0xfd -#define EVENT_CHECK_VECTOR 0xfc -#define CALL_FUNCTION_VECTOR 0xfb -#define KDB_VECTOR 0xfa - -/* - * Local APIC timer IRQ vector is on a different priority level, - * to work around the 'lost local interrupt if more than 2 IRQ - * sources per level' errata. - */ -#define LOCAL_TIMER_VECTOR 0xef - -/* - * First APIC vector available to drivers: (vectors 0x40-0xee) - * we start at 0x41 to spread out vectors evenly between priority - * levels. (0x82 is the hypercall vector) - */ -#define FIRST_DEVICE_VECTOR 0x41 -#define FIRST_SYSTEM_VECTOR 0xef - -extern int irq_vector[NR_IRQS]; +extern u8 irq_vector[NR_IRQ_VECTORS]; #define IO_APIC_VECTOR(irq) irq_vector[irq] +#define AUTO_ASSIGN -1 + +extern void (*interrupt[NR_IRQS])(void); -/* - * Various low-level irq details needed by irq.c, process.c, - * time.c, io_apic.c and smp.c - * - * Interrupt entry/exit code at both C and assembly level - */ +#define platform_legacy_irq(irq) ((irq) < 16) extern void mask_irq(unsigned int irq); extern void unmask_irq(unsigned int irq); diff --git a/xen/include/asm-x86/mach-default/apm.h b/xen/include/asm-x86/mach-default/apm.h new file mode 100644 index 0000000000..1f730b8bd1 --- /dev/null +++ b/xen/include/asm-x86/mach-default/apm.h @@ -0,0 +1,75 @@ +/* + * include/asm-i386/mach-default/apm.h + * + * Machine specific APM BIOS functions for generic. + * Split out from apm.c by Osamu Tomita + */ + +#ifndef _ASM_APM_H +#define _ASM_APM_H + +#ifdef APM_ZERO_SEGS +# define APM_DO_ZERO_SEGS \ + "pushl %%ds\n\t" \ + "pushl %%es\n\t" \ + "xorl %%edx, %%edx\n\t" \ + "mov %%dx, %%ds\n\t" \ + "mov %%dx, %%es\n\t" \ + "mov %%dx, %%fs\n\t" \ + "mov %%dx, %%gs\n\t" +# define APM_DO_POP_SEGS \ + "popl %%es\n\t" \ + "popl %%ds\n\t" +#else +# define APM_DO_ZERO_SEGS +# define APM_DO_POP_SEGS +#endif + +static inline void apm_bios_call_asm(u32 func, u32 ebx_in, u32 ecx_in, + u32 *eax, u32 *ebx, u32 *ecx, + u32 *edx, u32 *esi) +{ + /* + * N.B. We do NOT need a cld after the BIOS call + * because we always save and restore the flags. + */ + __asm__ __volatile__(APM_DO_ZERO_SEGS + "pushl %%edi\n\t" + "pushl %%ebp\n\t" + "lcall *%%cs:apm_bios_entry\n\t" + "setc %%al\n\t" + "popl %%ebp\n\t" + "popl %%edi\n\t" + APM_DO_POP_SEGS + : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx), + "=S" (*esi) + : "a" (func), "b" (ebx_in), "c" (ecx_in) + : "memory", "cc"); +} + +static inline u8 apm_bios_call_simple_asm(u32 func, u32 ebx_in, + u32 ecx_in, u32 *eax) +{ + int cx, dx, si; + u8 error; + + /* + * N.B. We do NOT need a cld after the BIOS call + * because we always save and restore the flags. + */ + __asm__ __volatile__(APM_DO_ZERO_SEGS + "pushl %%edi\n\t" + "pushl %%ebp\n\t" + "lcall *%%cs:apm_bios_entry\n\t" + "setc %%bl\n\t" + "popl %%ebp\n\t" + "popl %%edi\n\t" + APM_DO_POP_SEGS + : "=a" (*eax), "=b" (error), "=c" (cx), "=d" (dx), + "=S" (si) + : "a" (func), "b" (ebx_in), "c" (ecx_in) + : "memory", "cc"); + return error; +} + +#endif /* _ASM_APM_H */ diff --git a/xen/include/asm-x86/mach-default/bios_ebda.h b/xen/include/asm-x86/mach-default/bios_ebda.h new file mode 100644 index 0000000000..9cbd9a668a --- /dev/null +++ b/xen/include/asm-x86/mach-default/bios_ebda.h @@ -0,0 +1,15 @@ +#ifndef _MACH_BIOS_EBDA_H +#define _MACH_BIOS_EBDA_H + +/* + * there is a real-mode segmented pointer pointing to the + * 4K EBDA area at 0x40E. + */ +static inline unsigned int get_bios_ebda(void) +{ + unsigned int address = *(unsigned short *)phys_to_virt(0x40E); + address <<= 4; + return address; /* 0 means none */ +} + +#endif /* _MACH_BIOS_EBDA_H */ diff --git a/xen/include/asm-x86/mach-default/do_timer.h b/xen/include/asm-x86/mach-default/do_timer.h new file mode 100644 index 0000000000..03dd13a48a --- /dev/null +++ b/xen/include/asm-x86/mach-default/do_timer.h @@ -0,0 +1,85 @@ +/* defines for inline arch setup functions */ + +#include + +/** + * do_timer_interrupt_hook - hook into timer tick + * @regs: standard registers from interrupt + * + * Description: + * This hook is called immediately after the timer interrupt is ack'd. + * It's primary purpose is to allow architectures that don't possess + * individual per CPU clocks (like the CPU APICs supply) to broadcast the + * timer interrupt as a means of triggering reschedules etc. + **/ + +static inline void do_timer_interrupt_hook(struct pt_regs *regs) +{ + do_timer(regs); +#ifndef CONFIG_SMP + update_process_times(user_mode(regs)); +#endif +/* + * In the SMP case we use the local APIC timer interrupt to do the + * profiling, except when we simulate SMP mode on a uniprocessor + * system, in that case we have to call the local interrupt handler. + */ +#ifndef CONFIG_X86_LOCAL_APIC + profile_tick(CPU_PROFILING, regs); +#else + if (!using_apic_timer) + smp_local_timer_interrupt(regs); +#endif +} + + +/* you can safely undefine this if you don't have the Neptune chipset */ + +#define BUGGY_NEPTUN_TIMER + +/** + * do_timer_overflow - process a detected timer overflow condition + * @count: hardware timer interrupt count on overflow + * + * Description: + * This call is invoked when the jiffies count has not incremented but + * the hardware timer interrupt has. It means that a timer tick interrupt + * came along while the previous one was pending, thus a tick was missed + **/ +static inline int do_timer_overflow(int count) +{ + int i; + + spin_lock(&i8259A_lock); + /* + * This is tricky when I/O APICs are used; + * see do_timer_interrupt(). + */ + i = inb(0x20); + spin_unlock(&i8259A_lock); + + /* assumption about timer being IRQ0 */ + if (i & 0x01) { + /* + * We cannot detect lost timer interrupts ... + * well, that's why we call them lost, don't we? :) + * [hmm, on the Pentium and Alpha we can ... sort of] + */ + count -= LATCH; + } else { +#ifdef BUGGY_NEPTUN_TIMER + /* + * for the Neptun bug we know that the 'latch' + * command doesn't latch the high and low value + * of the counter atomically. Thus we have to + * substract 256 from the counter + * ... funny, isnt it? :) + */ + + count -= 256; +#else + printk("do_slow_gettimeoffset(): hardware timer problem?\n"); +#endif + } + return count; +} diff --git a/xen/include/asm-x86/mach-default/entry_arch.h b/xen/include/asm-x86/mach-default/entry_arch.h new file mode 100644 index 0000000000..bc861469bd --- /dev/null +++ b/xen/include/asm-x86/mach-default/entry_arch.h @@ -0,0 +1,34 @@ +/* + * This file is designed to contain the BUILD_INTERRUPT specifications for + * all of the extra named interrupt vectors used by the architecture. + * Usually this is the Inter Process Interrupts (IPIs) + */ + +/* + * The following vectors are part of the Linux architecture, there + * is no hardware IRQ pin equivalent for them, they are triggered + * through the ICC by us (IPIs) + */ +#ifdef CONFIG_X86_SMP +BUILD_INTERRUPT(reschedule_interrupt,RESCHEDULE_VECTOR) +BUILD_INTERRUPT(invalidate_interrupt,INVALIDATE_TLB_VECTOR) +BUILD_INTERRUPT(call_function_interrupt,CALL_FUNCTION_VECTOR) +#endif + +/* + * every pentium local APIC has two 'local interrupts', with a + * soft-definable vector attached to both interrupts, one of + * which is a timer interrupt, the other one is error counter + * overflow. Linux uses the local APIC timer interrupt to get + * a much simpler SMP time architecture: + */ +#ifdef CONFIG_X86_LOCAL_APIC +BUILD_INTERRUPT(apic_timer_interrupt,LOCAL_TIMER_VECTOR) +BUILD_INTERRUPT(error_interrupt,ERROR_APIC_VECTOR) +BUILD_INTERRUPT(spurious_interrupt,SPURIOUS_APIC_VECTOR) + +#ifdef CONFIG_X86_MCE_P4THERMAL +BUILD_INTERRUPT(thermal_interrupt,THERMAL_APIC_VECTOR) +#endif + +#endif diff --git a/xen/include/asm-x86/mach-default/io_ports.h b/xen/include/asm-x86/mach-default/io_ports.h new file mode 100644 index 0000000000..a96d9f6604 --- /dev/null +++ b/xen/include/asm-x86/mach-default/io_ports.h @@ -0,0 +1,30 @@ +/* + * arch/i386/mach-generic/io_ports.h + * + * Machine specific IO port address definition for generic. + * Written by Osamu Tomita + */ +#ifndef _MACH_IO_PORTS_H +#define _MACH_IO_PORTS_H + +/* i8253A PIT registers */ +#define PIT_MODE 0x43 +#define PIT_CH0 0x40 +#define PIT_CH2 0x42 + +/* i8259A PIC registers */ +#define PIC_MASTER_CMD 0x20 +#define PIC_MASTER_IMR 0x21 +#define PIC_MASTER_ISR PIC_MASTER_CMD +#define PIC_MASTER_POLL PIC_MASTER_ISR +#define PIC_MASTER_OCW3 PIC_MASTER_ISR +#define PIC_SLAVE_CMD 0xa0 +#define PIC_SLAVE_IMR 0xa1 + +/* i8259A PIC related value */ +#define PIC_CASCADE_IR 2 +#define MASTER_ICW4_DEFAULT 0x01 +#define SLAVE_ICW4_DEFAULT 0x01 +#define PIC_ICW4_AEOI 2 + +#endif /* !_MACH_IO_PORTS_H */ diff --git a/xen/include/asm-x86/mach-default/irq_vectors.h b/xen/include/asm-x86/mach-default/irq_vectors.h new file mode 100644 index 0000000000..de16b5bc9c --- /dev/null +++ b/xen/include/asm-x86/mach-default/irq_vectors.h @@ -0,0 +1,96 @@ +/* + * This file should contain #defines for all of the interrupt vector + * numbers used by this architecture. + * + * In addition, there are some standard defines: + * + * FIRST_EXTERNAL_VECTOR: + * The first free place for external interrupts + * + * SYSCALL_VECTOR: + * The IRQ vector a syscall makes the user to kernel transition + * under. + * + * TIMER_IRQ: + * The IRQ number the timer interrupt comes in at. + * + * NR_IRQS: + * The total number of interrupt vectors (including all the + * architecture specific interrupts) needed. + * + */ +#ifndef _ASM_IRQ_VECTORS_H +#define _ASM_IRQ_VECTORS_H + +/* + * IDT vectors usable for external interrupt sources start + * at 0x20: + */ +#define FIRST_EXTERNAL_VECTOR 0x20 + +#define HYPERCALL_VECTOR 0x82 + +/* + * Vectors 0x20-0x2f are used for ISA interrupts. + */ + +/* + * Special IRQ vectors used by the SMP architecture, 0xf0-0xff + * + * some of the following vectors are 'rare', they are merged + * into a single vector (CALL_FUNCTION_VECTOR) to save vector space. + * TLB, reschedule and local APIC vectors are performance-critical. + * + * Vectors 0xf0-0xfa are free (reserved for future Linux use). + */ +#define SPURIOUS_APIC_VECTOR 0xff +#define ERROR_APIC_VECTOR 0xfe +#define INVALIDATE_TLB_VECTOR 0xfd +#define EVENT_CHECK_VECTOR 0xfc +#define CALL_FUNCTION_VECTOR 0xfb + +#define THERMAL_APIC_VECTOR 0xf0 +/* + * Local APIC timer IRQ vector is on a different priority level, + * to work around the 'lost local interrupt if more than 2 IRQ + * sources per level' errata. + */ +#define LOCAL_TIMER_VECTOR 0xef + +/* + * First APIC vector available to drivers: (vectors 0x30-0xee) + * we start at 0x31 to spread out vectors evenly between priority + * levels. (0x80 is the syscall vector) + */ +#define FIRST_DEVICE_VECTOR 0x31 +#define FIRST_SYSTEM_VECTOR 0xef + +#define TIMER_IRQ 0 + +/* + * 16 8259A IRQ's, 208 potential APIC interrupt sources. + * Right now the APIC is mostly only used for SMP. + * 256 vectors is an architectural limit. (we can have + * more than 256 devices theoretically, but they will + * have to use shared interrupts) + * Since vectors 0x00-0x1f are used/reserved for the CPU, + * the usable vector space is 0x20-0xff (224 vectors) + */ + +/* + * The maximum number of vectors supported by i386 processors + * is limited to 256. For processors other than i386, NR_VECTORS + * should be changed accordingly. + */ +#define NR_VECTORS 256 + +#include "irq_vectors_limits.h" + +#define FPU_IRQ 13 + +#define FIRST_VM86_IRQ 3 +#define LAST_VM86_IRQ 15 +#define invalid_vm86_irq(irq) ((irq) < 3 || (irq) > 15) + + +#endif /* _ASM_IRQ_VECTORS_H */ diff --git a/xen/include/asm-x86/mach-default/irq_vectors_limits.h b/xen/include/asm-x86/mach-default/irq_vectors_limits.h new file mode 100644 index 0000000000..b330026e6f --- /dev/null +++ b/xen/include/asm-x86/mach-default/irq_vectors_limits.h @@ -0,0 +1,21 @@ +#ifndef _ASM_IRQ_VECTORS_LIMITS_H +#define _ASM_IRQ_VECTORS_LIMITS_H + +#ifdef CONFIG_PCI_MSI +#define NR_IRQS FIRST_SYSTEM_VECTOR +#define NR_IRQ_VECTORS NR_IRQS +#else +#ifdef CONFIG_X86_IO_APIC +#define NR_IRQS 224 +# if (224 >= 32 * NR_CPUS) +# define NR_IRQ_VECTORS NR_IRQS +# else +# define NR_IRQ_VECTORS (32 * NR_CPUS) +# endif +#else +#define NR_IRQS 16 +#define NR_IRQ_VECTORS NR_IRQS +#endif +#endif + +#endif /* _ASM_IRQ_VECTORS_LIMITS_H */ diff --git a/xen/include/asm-x86/mach-default/mach_apic.h b/xen/include/asm-x86/mach-default/mach_apic.h new file mode 100644 index 0000000000..4bf3c5ae34 --- /dev/null +++ b/xen/include/asm-x86/mach-default/mach_apic.h @@ -0,0 +1,133 @@ +#ifndef __ASM_MACH_APIC_H +#define __ASM_MACH_APIC_H + +#include +#include + +#define APIC_DFR_VALUE (APIC_DFR_FLAT) + +static inline cpumask_t target_cpus(void) +{ +#ifdef CONFIG_SMP + return cpu_online_map; +#else + return cpumask_of_cpu(0); +#endif +} +#define TARGET_CPUS (target_cpus()) + +#define NO_BALANCE_IRQ (0) +#define esr_disable (0) + +#define NO_IOAPIC_CHECK (0) + +#define INT_DELIVERY_MODE dest_LowestPrio +#define INT_DEST_MODE 1 /* logical delivery broadcast to all procs */ + +static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid) +{ + return physid_isset(apicid, bitmap); +} + +static inline unsigned long check_apicid_present(int bit) +{ + return physid_isset(bit, phys_cpu_present_map); +} + +/* + * Set up the logical destination ID. + * + * Intel recommends to set DFR, LDR and TPR before enabling + * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel + * document number 292116). So here it goes... + */ +static inline void init_apic_ldr(void) +{ + unsigned long val; + + apic_write_around(APIC_DFR, APIC_DFR_VALUE); + val = apic_read(APIC_LDR) & ~APIC_LDR_MASK; + val |= SET_APIC_LOGICAL_ID(1UL << smp_processor_id()); + apic_write_around(APIC_LDR, val); +} + +static inline physid_mask_t ioapic_phys_id_map(physid_mask_t phys_map) +{ + return phys_map; +} + +static inline void clustered_apic_check(void) +{ + printk("Enabling APIC mode: %s. Using %d I/O APICs\n", + "Flat", nr_ioapics); +} + +static inline int multi_timer_check(int apic, int irq) +{ + return 0; +} + +static inline int apicid_to_node(int logical_apicid) +{ + return 0; +} + +/* Mapping from cpu number to logical apicid */ +static inline int cpu_to_logical_apicid(int cpu) +{ + return 1 << cpu; +} + +static inline int cpu_present_to_apicid(int mps_cpu) +{ + if (mps_cpu < get_physical_broadcast()) + return mps_cpu; + else + return BAD_APICID; +} + +static inline physid_mask_t apicid_to_cpu_present(int phys_apicid) +{ + return physid_mask_of_physid(phys_apicid); +} + +static inline int mpc_apic_id(struct mpc_config_processor *m, + struct mpc_config_translation *translation_record) +{ + printk("Processor #%d %d:%d APIC version %d\n", + m->mpc_apicid, + (m->mpc_cpufeature & CPU_FAMILY_MASK) >> 8, + (m->mpc_cpufeature & CPU_MODEL_MASK) >> 4, + m->mpc_apicver); + return (m->mpc_apicid); +} + +static inline void setup_portio_remap(void) +{ +} + +static inline int check_phys_apicid_present(int boot_cpu_physical_apicid) +{ + return physid_isset(boot_cpu_physical_apicid, phys_cpu_present_map); +} + +static inline int apic_id_registered(void) +{ + return physid_isset(GET_APIC_ID(apic_read(APIC_ID)), phys_cpu_present_map); +} + +static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask) +{ + return cpus_addr(cpumask)[0]; +} + +static inline void enable_apic_mode(void) +{ +} + +static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb) +{ + return cpuid_apic >> index_msb; +} + +#endif /* __ASM_MACH_APIC_H */ diff --git a/xen/include/asm-x86/mach-default/mach_apicdef.h b/xen/include/asm-x86/mach-default/mach_apicdef.h new file mode 100644 index 0000000000..7bcb350c3e --- /dev/null +++ b/xen/include/asm-x86/mach-default/mach_apicdef.h @@ -0,0 +1,13 @@ +#ifndef __ASM_MACH_APICDEF_H +#define __ASM_MACH_APICDEF_H + +#define APIC_ID_MASK (0xF<<24) + +static inline unsigned get_apic_id(unsigned long x) +{ + return (((x)>>24)&0xF); +} + +#define GET_APIC_ID(x) get_apic_id(x) + +#endif diff --git a/xen/include/asm-x86/mach-default/mach_ipi.h b/xen/include/asm-x86/mach-default/mach_ipi.h new file mode 100644 index 0000000000..6f2b17a200 --- /dev/null +++ b/xen/include/asm-x86/mach-default/mach_ipi.h @@ -0,0 +1,30 @@ +#ifndef __ASM_MACH_IPI_H +#define __ASM_MACH_IPI_H + +void send_IPI_mask_bitmask(cpumask_t mask, int vector); +void __send_IPI_shortcut(unsigned int shortcut, int vector); + +static inline void send_IPI_mask(cpumask_t mask, int vector) +{ + send_IPI_mask_bitmask(mask, vector); +} + +static inline void send_IPI_allbutself(int vector) +{ + /* + * if there are no other CPUs in the system then we get an APIC send + * error if we try to broadcast, thus avoid sending IPIs in this case. + */ + if (!(num_online_cpus() > 1)) + return; + + __send_IPI_shortcut(APIC_DEST_ALLBUT, vector); + return; +} + +static inline void send_IPI_all(int vector) +{ + __send_IPI_shortcut(APIC_DEST_ALLINC, vector); +} + +#endif /* __ASM_MACH_IPI_H */ diff --git a/xen/include/asm-x86/mach-default/mach_mpparse.h b/xen/include/asm-x86/mach-default/mach_mpparse.h new file mode 100644 index 0000000000..1d38324825 --- /dev/null +++ b/xen/include/asm-x86/mach-default/mach_mpparse.h @@ -0,0 +1,28 @@ +#ifndef __ASM_MACH_MPPARSE_H +#define __ASM_MACH_MPPARSE_H + +static inline void mpc_oem_bus_info(struct mpc_config_bus *m, char *name, + struct mpc_config_translation *translation) +{ +// Dprintk("Bus #%d is %s\n", m->mpc_busid, name); +} + +static inline void mpc_oem_pci_bus(struct mpc_config_bus *m, + struct mpc_config_translation *translation) +{ +} + +static inline int mps_oem_check(struct mp_config_table *mpc, char *oem, + char *productid) +{ + return 0; +} + +/* Hook from generic ACPI tables.c */ +static inline int acpi_madt_oem_check(char *oem_id, char *oem_table_id) +{ + return 0; +} + + +#endif /* __ASM_MACH_MPPARSE_H */ diff --git a/xen/include/asm-x86/mach-default/mach_mpspec.h b/xen/include/asm-x86/mach-default/mach_mpspec.h new file mode 100644 index 0000000000..6b5dadcf1d --- /dev/null +++ b/xen/include/asm-x86/mach-default/mach_mpspec.h @@ -0,0 +1,8 @@ +#ifndef __ASM_MACH_MPSPEC_H +#define __ASM_MACH_MPSPEC_H + +#define MAX_IRQ_SOURCES 256 + +#define MAX_MP_BUSSES 32 + +#endif /* __ASM_MACH_MPSPEC_H */ diff --git a/xen/include/asm-x86/mach-default/mach_reboot.h b/xen/include/asm-x86/mach-default/mach_reboot.h new file mode 100644 index 0000000000..521e227db6 --- /dev/null +++ b/xen/include/asm-x86/mach-default/mach_reboot.h @@ -0,0 +1,30 @@ +/* + * arch/i386/mach-generic/mach_reboot.h + * + * Machine specific reboot functions for generic. + * Split out from reboot.c by Osamu Tomita + */ +#ifndef _MACH_REBOOT_H +#define _MACH_REBOOT_H + +static inline void kb_wait(void) +{ + int i; + + for (i = 0; i < 0x10000; i++) + if ((inb_p(0x64) & 0x02) == 0) + break; +} + +static inline void mach_reboot(void) +{ + int i; + for (i = 0; i < 100; i++) { + kb_wait(); + udelay(50); + outb(0xfe, 0x64); /* pulse reset low */ + udelay(50); + } +} + +#endif /* !_MACH_REBOOT_H */ diff --git a/xen/include/asm-x86/mach-default/mach_time.h b/xen/include/asm-x86/mach-default/mach_time.h new file mode 100644 index 0000000000..b749aa44a8 --- /dev/null +++ b/xen/include/asm-x86/mach-default/mach_time.h @@ -0,0 +1,122 @@ +/* + * include/asm-i386/mach-default/mach_time.h + * + * Machine specific set RTC function for generic. + * Split out from time.c by Osamu Tomita + */ +#ifndef _MACH_TIME_H +#define _MACH_TIME_H + +#include + +/* for check timing call set_rtc_mmss() 500ms */ +/* used in arch/i386/time.c::do_timer_interrupt() */ +#define USEC_AFTER 500000 +#define USEC_BEFORE 500000 + +/* + * In order to set the CMOS clock precisely, set_rtc_mmss has to be + * called 500 ms after the second nowtime has started, because when + * nowtime is written into the registers of the CMOS clock, it will + * jump to the next second precisely 500 ms later. Check the Motorola + * MC146818A or Dallas DS12887 data sheet for details. + * + * BUG: This routine does not handle hour overflow properly; it just + * sets the minutes. Usually you'll only notice that after reboot! + */ +static inline int mach_set_rtc_mmss(unsigned long nowtime) +{ + int retval = 0; + int real_seconds, real_minutes, cmos_minutes; + unsigned char save_control, save_freq_select; + + save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */ + CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); + + save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */ + CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); + + cmos_minutes = CMOS_READ(RTC_MINUTES); + if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) + BCD_TO_BIN(cmos_minutes); + + /* + * since we're only adjusting minutes and seconds, + * don't interfere with hour overflow. This avoids + * messing with unknown time zones but requires your + * RTC not to be off by more than 15 minutes + */ + real_seconds = nowtime % 60; + real_minutes = nowtime / 60; + if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) + real_minutes += 30; /* correct for half hour time zone */ + real_minutes %= 60; + + if (abs(real_minutes - cmos_minutes) < 30) { + if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { + BIN_TO_BCD(real_seconds); + BIN_TO_BCD(real_minutes); + } + CMOS_WRITE(real_seconds,RTC_SECONDS); + CMOS_WRITE(real_minutes,RTC_MINUTES); + } else { + printk(KERN_WARNING + "set_rtc_mmss: can't update from %d to %d\n", + cmos_minutes, real_minutes); + retval = -1; + } + + /* The following flags have to be released exactly in this order, + * otherwise the DS12887 (popular MC146818A clone with integrated + * battery and quartz) will not reset the oscillator and will not + * update precisely 500 ms later. You won't find this mentioned in + * the Dallas Semiconductor data sheets, but who believes data + * sheets anyway ... -- Markus Kuhn + */ + CMOS_WRITE(save_control, RTC_CONTROL); + CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); + + return retval; +} + +static inline unsigned long mach_get_cmos_time(void) +{ + unsigned int year, mon, day, hour, min, sec; + int i; + + /* The Linux interpretation of the CMOS clock register contents: + * When the Update-In-Progress (UIP) flag goes from 1 to 0, the + * RTC registers show the second which has precisely just started. + * Let's hope other operating systems interpret the RTC the same way. + */ + /* read RTC exactly on falling edge of update flag */ + for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */ + if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) + break; + for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */ + if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) + break; + do { /* Isn't this overkill ? UIP above should guarantee consistency */ + sec = CMOS_READ(RTC_SECONDS); + min = CMOS_READ(RTC_MINUTES); + hour = CMOS_READ(RTC_HOURS); + day = CMOS_READ(RTC_DAY_OF_MONTH); + mon = CMOS_READ(RTC_MONTH); + year = CMOS_READ(RTC_YEAR); + } while (sec != CMOS_READ(RTC_SECONDS)); + if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) + { + BCD_TO_BIN(sec); + BCD_TO_BIN(min); + BCD_TO_BIN(hour); + BCD_TO_BIN(day); + BCD_TO_BIN(mon); + BCD_TO_BIN(year); + } + if ((year += 1900) < 1970) + year += 100; + + return mktime(year, mon, day, hour, min, sec); +} + +#endif /* !_MACH_TIME_H */ diff --git a/xen/include/asm-x86/mach-default/mach_timer.h b/xen/include/asm-x86/mach-default/mach_timer.h new file mode 100644 index 0000000000..4b9703bb02 --- /dev/null +++ b/xen/include/asm-x86/mach-default/mach_timer.h @@ -0,0 +1,48 @@ +/* + * include/asm-i386/mach-default/mach_timer.h + * + * Machine specific calibrate_tsc() for generic. + * Split out from timer_tsc.c by Osamu Tomita + */ +/* ------ Calibrate the TSC ------- + * Return 2^32 * (1 / (TSC clocks per usec)) for do_fast_gettimeoffset(). + * Too much 64-bit arithmetic here to do this cleanly in C, and for + * accuracy's sake we want to keep the overhead on the CTC speaker (channel 2) + * output busy loop as low as possible. We avoid reading the CTC registers + * directly because of the awkward 8-bit access mechanism of the 82C54 + * device. + */ +#ifndef _MACH_TIMER_H +#define _MACH_TIMER_H + +#define CALIBRATE_LATCH (5 * LATCH) + +static inline void mach_prepare_counter(void) +{ + /* Set the Gate high, disable speaker */ + outb((inb(0x61) & ~0x02) | 0x01, 0x61); + + /* + * Now let's take care of CTC channel 2 + * + * Set the Gate high, program CTC channel 2 for mode 0, + * (interrupt on terminal count mode), binary count, + * load 5 * LATCH count, (LSB and MSB) to begin countdown. + * + * Some devices need a delay here. + */ + outb(0xb0, 0x43); /* binary, mode 0, LSB/MSB, Ch 2 */ + outb_p(CALIBRATE_LATCH & 0xff, 0x42); /* LSB of count */ + outb_p(CALIBRATE_LATCH >> 8, 0x42); /* MSB of count */ +} + +static inline void mach_countup(unsigned long *count_p) +{ + unsigned long count = 0; + do { + count++; + } while ((inb_p(0x61) & 0x20) == 0); + *count_p = count; +} + +#endif /* !_MACH_TIMER_H */ diff --git a/xen/include/asm-x86/mach-default/mach_traps.h b/xen/include/asm-x86/mach-default/mach_traps.h new file mode 100644 index 0000000000..c98c2880c5 --- /dev/null +++ b/xen/include/asm-x86/mach-default/mach_traps.h @@ -0,0 +1,29 @@ +/* + * include/asm-i386/mach-default/mach_traps.h + * + * Machine specific NMI handling for generic. + * Split out from traps.c by Osamu Tomita + */ +#ifndef _MACH_TRAPS_H +#define _MACH_TRAPS_H + +static inline void clear_mem_error(unsigned char reason) +{ + reason = (reason & 0xf) | 4; + outb(reason, 0x61); +} + +static inline unsigned char get_nmi_reason(void) +{ + return inb(0x61); +} + +static inline void reassert_nmi(void) +{ + outb(0x8f, 0x70); + inb(0x71); /* dummy */ + outb(0x0f, 0x70); + inb(0x71); /* dummy */ +} + +#endif /* !_MACH_TRAPS_H */ diff --git a/xen/include/asm-x86/mach-default/mach_wakecpu.h b/xen/include/asm-x86/mach-default/mach_wakecpu.h new file mode 100644 index 0000000000..673b85c9b2 --- /dev/null +++ b/xen/include/asm-x86/mach-default/mach_wakecpu.h @@ -0,0 +1,41 @@ +#ifndef __ASM_MACH_WAKECPU_H +#define __ASM_MACH_WAKECPU_H + +/* + * This file copes with machines that wakeup secondary CPUs by the + * INIT, INIT, STARTUP sequence. + */ + +#define WAKE_SECONDARY_VIA_INIT + +#define TRAMPOLINE_LOW phys_to_virt(0x467) +#define TRAMPOLINE_HIGH phys_to_virt(0x469) + +#define boot_cpu_apicid boot_cpu_physical_apicid + +static inline void wait_for_init_deassert(atomic_t *deassert) +{ + while (!atomic_read(deassert)); + return; +} + +/* Nothing to do for most platforms, since cleared by the INIT cycle */ +static inline void smp_callin_clear_local_apic(void) +{ +} + +static inline void store_NMI_vector(unsigned short *high, unsigned short *low) +{ +} + +static inline void restore_NMI_vector(unsigned short *high, unsigned short *low) +{ +} + +#if APIC_DEBUG + #define inquire_remote_apic(apicid) __inquire_remote_apic(apicid) +#else + #define inquire_remote_apic(apicid) {} +#endif + +#endif /* __ASM_MACH_WAKECPU_H */ diff --git a/xen/include/asm-x86/mach-default/pci-functions.h b/xen/include/asm-x86/mach-default/pci-functions.h new file mode 100644 index 0000000000..ed0bab4273 --- /dev/null +++ b/xen/include/asm-x86/mach-default/pci-functions.h @@ -0,0 +1,19 @@ +/* + * PCI BIOS function numbering for conventional PCI BIOS + * systems + */ + +#define PCIBIOS_PCI_FUNCTION_ID 0xb1XX +#define PCIBIOS_PCI_BIOS_PRESENT 0xb101 +#define PCIBIOS_FIND_PCI_DEVICE 0xb102 +#define PCIBIOS_FIND_PCI_CLASS_CODE 0xb103 +#define PCIBIOS_GENERATE_SPECIAL_CYCLE 0xb106 +#define PCIBIOS_READ_CONFIG_BYTE 0xb108 +#define PCIBIOS_READ_CONFIG_WORD 0xb109 +#define PCIBIOS_READ_CONFIG_DWORD 0xb10a +#define PCIBIOS_WRITE_CONFIG_BYTE 0xb10b +#define PCIBIOS_WRITE_CONFIG_WORD 0xb10c +#define PCIBIOS_WRITE_CONFIG_DWORD 0xb10d +#define PCIBIOS_GET_ROUTING_OPTIONS 0xb10e +#define PCIBIOS_SET_PCI_HW_INT 0xb10f + diff --git a/xen/include/asm-x86/mach-default/setup_arch_post.h b/xen/include/asm-x86/mach-default/setup_arch_post.h new file mode 100644 index 0000000000..2fc4888721 --- /dev/null +++ b/xen/include/asm-x86/mach-default/setup_arch_post.h @@ -0,0 +1,40 @@ +/** + * machine_specific_memory_setup - Hook for machine specific memory setup. + * + * Description: + * This is included late in kernel/setup.c so that it can make + * use of all of the static functions. + **/ + +static char * __init machine_specific_memory_setup(void) +{ + char *who; + + + who = "BIOS-e820"; + + /* + * Try to copy the BIOS-supplied E820-map. + * + * Otherwise fake a memory map; one section from 0k->640k, + * the next section from 1mb->appropriate_mem_k + */ + sanitize_e820_map(E820_MAP, &E820_MAP_NR); + if (copy_e820_map(E820_MAP, E820_MAP_NR) < 0) { + unsigned long mem_size; + + /* compare results from other methods and take the greater */ + if (ALT_MEM_K < EXT_MEM_K) { + mem_size = EXT_MEM_K; + who = "BIOS-88"; + } else { + mem_size = ALT_MEM_K; + who = "BIOS-e801"; + } + + e820.nr_map = 0; + add_memory_region(0, LOWMEMSIZE(), E820_RAM); + add_memory_region(HIGH_MEMORY, mem_size << 10, E820_RAM); + } + return who; +} diff --git a/xen/include/asm-x86/mach-default/setup_arch_pre.h b/xen/include/asm-x86/mach-default/setup_arch_pre.h new file mode 100644 index 0000000000..fb42099e7b --- /dev/null +++ b/xen/include/asm-x86/mach-default/setup_arch_pre.h @@ -0,0 +1,5 @@ +/* Hook to call BIOS initialisation function */ + +/* no action for generic */ + +#define ARCH_SETUP diff --git a/xen/include/asm-x86/mach-default/smpboot_hooks.h b/xen/include/asm-x86/mach-default/smpboot_hooks.h new file mode 100644 index 0000000000..7f45f63110 --- /dev/null +++ b/xen/include/asm-x86/mach-default/smpboot_hooks.h @@ -0,0 +1,44 @@ +/* two abstractions specific to kernel/smpboot.c, mainly to cater to visws + * which needs to alter them. */ + +static inline void smpboot_clear_io_apic_irqs(void) +{ + io_apic_irqs = 0; +} + +static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip) +{ + CMOS_WRITE(0xa, 0xf); + local_flush_tlb(); + Dprintk("1.\n"); + *((volatile unsigned short *) TRAMPOLINE_HIGH) = start_eip >> 4; + Dprintk("2.\n"); + *((volatile unsigned short *) TRAMPOLINE_LOW) = start_eip & 0xf; + Dprintk("3.\n"); +} + +static inline void smpboot_restore_warm_reset_vector(void) +{ + /* + * Install writable page 0 entry to set BIOS data area. + */ + local_flush_tlb(); + + /* + * Paranoid: Set warm reset code and vector here back + * to default values. + */ + CMOS_WRITE(0, 0xf); + + *((volatile long *) phys_to_virt(0x467)) = 0; +} + +static inline void smpboot_setup_io_apic(void) +{ + /* + * Here we can be sure that there is an IO-APIC in the system. Let's + * go and set it up: + */ + if (!skip_ioapic_setup && nr_ioapics) + setup_IO_APIC(); +} diff --git a/xen/include/asm-x86/mach_apic.h b/xen/include/asm-x86/mach_apic.h deleted file mode 100644 index e93b0808d5..0000000000 --- a/xen/include/asm-x86/mach_apic.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * based on linux-2.6.10/include/asm-i386/mach-default/mach_apic.h - * - */ -#ifndef __ASM_MACH_APIC_H -#define __ASM_MACH_APIC_H - -#define APIC_DFR_VALUE (APIC_DFR_FLAT) -#define esr_disable (0) - -/* - * Set up the logical destination ID. - * - * Intel recommends to set DFR, LDR and TPR before enabling - * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel - * document number 292116). So here it goes... - */ -static inline void init_apic_ldr(void) -{ - unsigned long val; - - apic_write_around(APIC_DFR, APIC_DFR_VALUE); - val = apic_read(APIC_LDR) & ~APIC_LDR_MASK; - val |= SET_APIC_LOGICAL_ID(1UL << smp_processor_id()); - apic_write_around(APIC_LDR, val); -} - -static inline int apic_id_registered(void) -{ - return test_bit(GET_APIC_ID(apic_read(APIC_ID)), &phys_cpu_present_map); -} -#endif /* __ASM_MACH_APIC_H */ diff --git a/xen/include/asm-x86/mpspec.h b/xen/include/asm-x86/mpspec.h index 1e73671c25..7add527173 100644 --- a/xen/include/asm-x86/mpspec.h +++ b/xen/include/asm-x86/mpspec.h @@ -1,242 +1,84 @@ #ifndef __ASM_MPSPEC_H #define __ASM_MPSPEC_H -#include -#include +#include +#include +#include -/* - * Structure definitions for SMP machines following the - * Intel Multiprocessing Specification 1.1 and 1.4. - */ - -/* - * This tag identifies where the SMP configuration - * information is. - */ - -#define SMP_MAGIC_IDENT (('_'<<24)|('P'<<16)|('M'<<8)|'_') - -/* - * a maximum of 16 APICs with the current APIC ID architecture. - * xAPICs can have up to 256. SAPICs have 16 ID bits. - */ -#ifdef CONFIG_X86_CLUSTERED_APIC -#define MAX_APICS 256 -#else -#define MAX_APICS 16 -#endif - -#define MAX_MPC_ENTRY 1024 - -struct intel_mp_floating -{ - char mpf_signature[4]; /* "_MP_" */ - unsigned int mpf_physptr; /* Configuration table address */ - unsigned char mpf_length; /* Our length (paragraphs) */ - unsigned char mpf_specification;/* Specification version */ - unsigned char mpf_checksum; /* Checksum (makes sum 0) */ - unsigned char mpf_feature1; /* Standard or configuration ? */ - unsigned char mpf_feature2; /* Bit7 set for IMCR|PIC */ - unsigned char mpf_feature3; /* Unused (0) */ - unsigned char mpf_feature4; /* Unused (0) */ - unsigned char mpf_feature5; /* Unused (0) */ -}; - -struct mp_config_table -{ - char mpc_signature[4]; -#define MPC_SIGNATURE "PCMP" - unsigned short mpc_length; /* Size of table */ - char mpc_spec; /* 0x01 */ - char mpc_checksum; - char mpc_oem[8]; - char mpc_productid[12]; - unsigned int mpc_oemptr; /* 0 if not present */ - unsigned short mpc_oemsize; /* 0 if not present */ - unsigned short mpc_oemcount; - unsigned int mpc_lapic; /* APIC address */ - unsigned int reserved; -}; - -/* Followed by entries */ - -#define MP_PROCESSOR 0 -#define MP_BUS 1 -#define MP_IOAPIC 2 -#define MP_INTSRC 3 -#define MP_LINTSRC 4 -#define MP_TRANSLATION 192 /* Used by IBM NUMA-Q to describe node locality */ - -struct mpc_config_processor -{ - unsigned char mpc_type; - unsigned char mpc_apicid; /* Local APIC number */ - unsigned char mpc_apicver; /* Its versions */ - unsigned char mpc_cpuflag; -#define CPU_ENABLED 1 /* Processor is available */ -#define CPU_BOOTPROCESSOR 2 /* Processor is the BP */ - unsigned int mpc_cpufeature; -#define CPU_STEPPING_MASK 0x0F -#define CPU_MODEL_MASK 0xF0 -#define CPU_FAMILY_MASK 0xF00 - unsigned int mpc_featureflag; /* CPUID feature value */ - unsigned int mpc_reserved[2]; -}; - -struct mpc_config_bus -{ - unsigned char mpc_type; - unsigned char mpc_busid; - unsigned char mpc_bustype[6] __attribute((packed)); -}; - -/* List of Bus Type string values, Intel MP Spec. */ -#define BUSTYPE_EISA "EISA" -#define BUSTYPE_ISA "ISA" -#define BUSTYPE_INTERN "INTERN" /* Internal BUS */ -#define BUSTYPE_MCA "MCA" -#define BUSTYPE_VL "VL" /* Local bus */ -#define BUSTYPE_PCI "PCI" -#define BUSTYPE_PCMCIA "PCMCIA" -#define BUSTYPE_CBUS "CBUS" -#define BUSTYPE_CBUSII "CBUSII" -#define BUSTYPE_FUTURE "FUTURE" -#define BUSTYPE_MBI "MBI" -#define BUSTYPE_MBII "MBII" -#define BUSTYPE_MPI "MPI" -#define BUSTYPE_MPSA "MPSA" -#define BUSTYPE_NUBUS "NUBUS" -#define BUSTYPE_TC "TC" -#define BUSTYPE_VME "VME" -#define BUSTYPE_XPRESS "XPRESS" - -struct mpc_config_ioapic -{ - unsigned char mpc_type; - unsigned char mpc_apicid; - unsigned char mpc_apicver; - unsigned char mpc_flags; -#define MPC_APIC_USABLE 0x01 - unsigned int mpc_apicaddr; -}; - -struct mpc_config_intsrc -{ - unsigned char mpc_type; - unsigned char mpc_irqtype; - unsigned short mpc_irqflag; - unsigned char mpc_srcbus; - unsigned char mpc_srcbusirq; - unsigned char mpc_dstapic; - unsigned char mpc_dstirq; -}; - -enum mp_irq_source_types { - mp_INT = 0, - mp_NMI = 1, - mp_SMI = 2, - mp_ExtINT = 3 -}; - -#define MP_IRQDIR_DEFAULT 0 -#define MP_IRQDIR_HIGH 1 -#define MP_IRQDIR_LOW 3 - - -struct mpc_config_lintsrc -{ - unsigned char mpc_type; - unsigned char mpc_irqtype; - unsigned short mpc_irqflag; - unsigned char mpc_srcbusid; - unsigned char mpc_srcbusirq; - unsigned char mpc_destapic; -#define MP_APIC_ALL 0xFF - unsigned char mpc_destapiclint; -}; - -struct mp_config_oemtable -{ - char oem_signature[4]; -#define MPC_OEM_SIGNATURE "_OEM" - unsigned short oem_length; /* Size of table */ - char oem_rev; /* 0x01 */ - char oem_checksum; - char mpc_oem[8]; -}; - -struct mpc_config_translation -{ - unsigned char mpc_type; - unsigned char trans_len; - unsigned char trans_type; - unsigned char trans_quad; - unsigned char trans_global; - unsigned char trans_local; - unsigned short trans_reserved; -}; - -/* - * Default configurations - * - * 1 2 CPU ISA 82489DX - * 2 2 CPU EISA 82489DX neither IRQ 0 timer nor IRQ 13 DMA chaining - * 3 2 CPU EISA 82489DX - * 4 2 CPU MCA 82489DX - * 5 2 CPU ISA+PCI - * 6 2 CPU EISA+PCI - * 7 2 CPU MCA+PCI - */ - -#ifdef CONFIG_MULTIQUAD -#define MAX_IRQ_SOURCES 512 -#else /* !CONFIG_MULTIQUAD */ -#define MAX_IRQ_SOURCES 256 -#endif /* CONFIG_MULTIQUAD */ - -#define MAX_MP_BUSSES 32 -enum mp_bustype { - MP_BUS_ISA = 1, - MP_BUS_EISA, - MP_BUS_PCI, - MP_BUS_MCA -}; -extern int *mp_bus_id_to_type; -extern int *mp_bus_id_to_node; -extern int *mp_bus_id_to_local; -extern int *mp_bus_id_to_pci_bus; +extern int mp_bus_id_to_type [MAX_MP_BUSSES]; +extern int mp_bus_id_to_node [MAX_MP_BUSSES]; +extern int mp_bus_id_to_local [MAX_MP_BUSSES]; extern int quad_local_to_mp_bus_id [NR_CPUS/4][4]; +extern int mp_bus_id_to_pci_bus [MAX_MP_BUSSES]; extern unsigned int boot_cpu_physical_apicid; -/*extern unsigned long phys_cpu_present_map;*/ extern int smp_found_config; extern void find_smp_config (void); extern void get_smp_config (void); -/*extern int nr_ioapics;*/ +extern int nr_ioapics; extern int apic_version [MAX_APICS]; -/*extern int mp_irq_entries;*/ -/*extern struct mpc_config_intsrc *mp_irqs;*/ -/*extern int mpc_default_type;*/ +extern int mp_bus_id_to_type [MAX_MP_BUSSES]; +extern int mp_irq_entries; +extern struct mpc_config_intsrc mp_irqs [MAX_IRQ_SOURCES]; +extern int mpc_default_type; +extern int mp_bus_id_to_pci_bus [MAX_MP_BUSSES]; extern int mp_current_pci_id; extern unsigned long mp_lapic_addr; -/*extern int pic_mode;*/ +extern int pic_mode; extern int using_apic_timer; #ifdef CONFIG_ACPI_BOOT extern void mp_register_lapic (u8 id, u8 enabled); extern void mp_register_lapic_address (u64 address); - -#ifdef CONFIG_X86_IO_APIC -extern void mp_register_ioapic (u8 id, u32 address, u32 irq_base); -extern void mp_override_legacy_irq (u8 bus_irq, u8 polarity, u8 trigger, u32 global_irq); +extern void mp_register_ioapic (u8 id, u32 address, u32 gsi_base); +extern void mp_override_legacy_irq (u8 bus_irq, u8 polarity, u8 trigger, u32 gsi); extern void mp_config_acpi_legacy_irqs (void); -extern void mp_config_ioapic_for_sci(int irq); -extern void mp_parse_prt (void); -#else /*!CONFIG_X86_IO_APIC*/ -static inline void mp_config_ioapic_for_sci(int irq) { } -#endif /*!CONFIG_X86_IO_APIC*/ - +extern int mp_register_gsi (u32 gsi, int edge_level, int active_high_low); #endif /*CONFIG_ACPI_BOOT*/ +#define PHYSID_ARRAY_SIZE BITS_TO_LONGS(MAX_APICS) + +struct physid_mask +{ + unsigned long mask[PHYSID_ARRAY_SIZE]; +}; + +typedef struct physid_mask physid_mask_t; + +#define physid_set(physid, map) set_bit(physid, (map).mask) +#define physid_clear(physid, map) clear_bit(physid, (map).mask) +#define physid_isset(physid, map) test_bit(physid, (map).mask) +#define physid_test_and_set(physid, map) test_and_set_bit(physid, (map).mask) + +#define physids_and(dst, src1, src2) bitmap_and((dst).mask, (src1).mask, (src2).mask, MAX_APICS) +#define physids_or(dst, src1, src2) bitmap_or((dst).mask, (src1).mask, (src2).mask, MAX_APICS) +#define physids_clear(map) bitmap_zero((map).mask, MAX_APICS) +#define physids_complement(dst, src) bitmap_complement((dst).mask,(src).mask, MAX_APICS) +#define physids_empty(map) bitmap_empty((map).mask, MAX_APICS) +#define physids_equal(map1, map2) bitmap_equal((map1).mask, (map2).mask, MAX_APICS) +#define physids_weight(map) bitmap_weight((map).mask, MAX_APICS) +#define physids_shift_right(d, s, n) bitmap_shift_right((d).mask, (s).mask, n, MAX_APICS) +#define physids_shift_left(d, s, n) bitmap_shift_left((d).mask, (s).mask, n, MAX_APICS) +#define physids_coerce(map) ((map).mask[0]) + +#define physids_promote(physids) \ + ({ \ + physid_mask_t __physid_mask = PHYSID_MASK_NONE; \ + __physid_mask.mask[0] = physids; \ + __physid_mask; \ + }) + +#define physid_mask_of_physid(physid) \ + ({ \ + physid_mask_t __physid_mask = PHYSID_MASK_NONE; \ + physid_set(physid, __physid_mask); \ + __physid_mask; \ + }) + +#define PHYSID_MASK_ALL { {[0 ... PHYSID_ARRAY_SIZE-1] = ~0UL} } +#define PHYSID_MASK_NONE { {[0 ... PHYSID_ARRAY_SIZE-1] = 0UL} } + +extern physid_mask_t phys_cpu_present_map; + #endif diff --git a/xen/include/asm-x86/mpspec_def.h b/xen/include/asm-x86/mpspec_def.h new file mode 100644 index 0000000000..902c030f7f --- /dev/null +++ b/xen/include/asm-x86/mpspec_def.h @@ -0,0 +1,188 @@ +#ifndef __ASM_MPSPEC_DEF_H +#define __ASM_MPSPEC_DEF_H + +/* + * Structure definitions for SMP machines following the + * Intel Multiprocessing Specification 1.1 and 1.4. + */ + +/* + * This tag identifies where the SMP configuration + * information is. + */ + +#define SMP_MAGIC_IDENT (('_'<<24)|('P'<<16)|('M'<<8)|'_') + +#define MAX_MPC_ENTRY 1024 +#define MAX_APICS 256 + +struct intel_mp_floating +{ + char mpf_signature[4]; /* "_MP_" */ + unsigned int mpf_physptr; /* Configuration table address */ + unsigned char mpf_length; /* Our length (paragraphs) */ + unsigned char mpf_specification;/* Specification version */ + unsigned char mpf_checksum; /* Checksum (makes sum 0) */ + unsigned char mpf_feature1; /* Standard or configuration ? */ + unsigned char mpf_feature2; /* Bit7 set for IMCR|PIC */ + unsigned char mpf_feature3; /* Unused (0) */ + unsigned char mpf_feature4; /* Unused (0) */ + unsigned char mpf_feature5; /* Unused (0) */ +}; + +struct mp_config_table +{ + char mpc_signature[4]; +#define MPC_SIGNATURE "PCMP" + unsigned short mpc_length; /* Size of table */ + char mpc_spec; /* 0x01 */ + char mpc_checksum; + char mpc_oem[8]; + char mpc_productid[12]; + unsigned int mpc_oemptr; /* 0 if not present */ + unsigned short mpc_oemsize; /* 0 if not present */ + unsigned short mpc_oemcount; + unsigned int mpc_lapic; /* APIC address */ + unsigned int reserved; +}; + +/* Followed by entries */ + +#define MP_PROCESSOR 0 +#define MP_BUS 1 +#define MP_IOAPIC 2 +#define MP_INTSRC 3 +#define MP_LINTSRC 4 +#define MP_TRANSLATION 192 /* Used by IBM NUMA-Q to describe node locality */ + +struct mpc_config_processor +{ + unsigned char mpc_type; + unsigned char mpc_apicid; /* Local APIC number */ + unsigned char mpc_apicver; /* Its versions */ + unsigned char mpc_cpuflag; +#define CPU_ENABLED 1 /* Processor is available */ +#define CPU_BOOTPROCESSOR 2 /* Processor is the BP */ + unsigned int mpc_cpufeature; +#define CPU_STEPPING_MASK 0x0F +#define CPU_MODEL_MASK 0xF0 +#define CPU_FAMILY_MASK 0xF00 + unsigned int mpc_featureflag; /* CPUID feature value */ + unsigned int mpc_reserved[2]; +}; + +struct mpc_config_bus +{ + unsigned char mpc_type; + unsigned char mpc_busid; + unsigned char mpc_bustype[6] __attribute((packed)); +}; + +/* List of Bus Type string values, Intel MP Spec. */ +#define BUSTYPE_EISA "EISA" +#define BUSTYPE_ISA "ISA" +#define BUSTYPE_INTERN "INTERN" /* Internal BUS */ +#define BUSTYPE_MCA "MCA" +#define BUSTYPE_VL "VL" /* Local bus */ +#define BUSTYPE_PCI "PCI" +#define BUSTYPE_PCMCIA "PCMCIA" +#define BUSTYPE_CBUS "CBUS" +#define BUSTYPE_CBUSII "CBUSII" +#define BUSTYPE_FUTURE "FUTURE" +#define BUSTYPE_MBI "MBI" +#define BUSTYPE_MBII "MBII" +#define BUSTYPE_MPI "MPI" +#define BUSTYPE_MPSA "MPSA" +#define BUSTYPE_NUBUS "NUBUS" +#define BUSTYPE_TC "TC" +#define BUSTYPE_VME "VME" +#define BUSTYPE_XPRESS "XPRESS" +#define BUSTYPE_NEC98 "NEC98" + +struct mpc_config_ioapic +{ + unsigned char mpc_type; + unsigned char mpc_apicid; + unsigned char mpc_apicver; + unsigned char mpc_flags; +#define MPC_APIC_USABLE 0x01 + unsigned int mpc_apicaddr; +}; + +struct mpc_config_intsrc +{ + unsigned char mpc_type; + unsigned char mpc_irqtype; + unsigned short mpc_irqflag; + unsigned char mpc_srcbus; + unsigned char mpc_srcbusirq; + unsigned char mpc_dstapic; + unsigned char mpc_dstirq; +}; + +enum mp_irq_source_types { + mp_INT = 0, + mp_NMI = 1, + mp_SMI = 2, + mp_ExtINT = 3 +}; + +#define MP_IRQDIR_DEFAULT 0 +#define MP_IRQDIR_HIGH 1 +#define MP_IRQDIR_LOW 3 + + +struct mpc_config_lintsrc +{ + unsigned char mpc_type; + unsigned char mpc_irqtype; + unsigned short mpc_irqflag; + unsigned char mpc_srcbusid; + unsigned char mpc_srcbusirq; + unsigned char mpc_destapic; +#define MP_APIC_ALL 0xFF + unsigned char mpc_destapiclint; +}; + +struct mp_config_oemtable +{ + char oem_signature[4]; +#define MPC_OEM_SIGNATURE "_OEM" + unsigned short oem_length; /* Size of table */ + char oem_rev; /* 0x01 */ + char oem_checksum; + char mpc_oem[8]; +}; + +struct mpc_config_translation +{ + unsigned char mpc_type; + unsigned char trans_len; + unsigned char trans_type; + unsigned char trans_quad; + unsigned char trans_global; + unsigned char trans_local; + unsigned short trans_reserved; +}; + +/* + * Default configurations + * + * 1 2 CPU ISA 82489DX + * 2 2 CPU EISA 82489DX neither IRQ 0 timer nor IRQ 13 DMA chaining + * 3 2 CPU EISA 82489DX + * 4 2 CPU MCA 82489DX + * 5 2 CPU ISA+PCI + * 6 2 CPU EISA+PCI + * 7 2 CPU MCA+PCI + */ + +enum mp_bustype { + MP_BUS_ISA = 1, + MP_BUS_EISA, + MP_BUS_PCI, + MP_BUS_MCA, + MP_BUS_NEC98 +}; +#endif + diff --git a/xen/include/asm-x86/page.h b/xen/include/asm-x86/page.h index 59e582e4cd..64b0635ce6 100644 --- a/xen/include/asm-x86/page.h +++ b/xen/include/asm-x86/page.h @@ -131,8 +131,6 @@ static __inline__ int get_order(unsigned long size) return order; } -extern void zap_low_mappings(void); - /* Map physical byte range (@p, @p+@s) at virt address @v in pagetable @pt. */ extern int map_pages( diff --git a/xen/include/asm-x86/processor.h b/xen/include/asm-x86/processor.h index d31b9769b9..8cd4755cba 100644 --- a/xen/include/asm-x86/processor.h +++ b/xen/include/asm-x86/processor.h @@ -5,16 +5,13 @@ #define __ASM_X86_PROCESSOR_H #ifndef __ASSEMBLY__ -#include -#include -#include -#include -#include #include -#include #include -#include +#include #include +#include +#include +#include #endif /* @@ -166,7 +163,7 @@ struct cpuinfo_x86 { int x86_cache_size; /* in KB - for CPUS that support this call */ int x86_clflush_size; int x86_tlbsize; /* number of 4K pages in DTLB/ITLB combined */ -} __attribute__((__aligned__(SMP_CACHE_BYTES))); +} __cacheline_aligned; /* * capabilities of CPUs @@ -369,7 +366,7 @@ struct tss_struct { u16 bitmap; /* Pads the TSS to be cacheline-aligned (total size is 0x80). */ u8 __cacheline_filler[24]; -} __cacheline_aligned PACKED; +} __cacheline_aligned __attribute__((packed)); #define IDT_ENTRIES 256 extern idt_entry_t idt_table[]; diff --git a/xen/include/asm-x86/smp.h b/xen/include/asm-x86/smp.h index e1e9443035..f8edfd1fca 100644 --- a/xen/include/asm-x86/smp.h +++ b/xen/include/asm-x86/smp.h @@ -1,14 +1,28 @@ #ifndef __ASM_SMP_H #define __ASM_SMP_H +/* + * We need the APIC definitions automatically as part of 'smp.h' + */ #ifndef __ASSEMBLY__ #include +#include +#include +#endif + +#ifdef CONFIG_X86_LOCAL_APIC +#ifndef __ASSEMBLY__ #include +#include #include +#ifdef CONFIG_X86_IO_APIC #include +#endif #include #endif +#endif +#define BAD_APICID 0xFFu #ifdef CONFIG_SMP #ifndef __ASSEMBLY__ @@ -17,79 +31,61 @@ */ extern void smp_alloc_memory(void); -extern unsigned long phys_cpu_present_map; -extern unsigned long cpu_online_map; -extern volatile unsigned long smp_invalidate_needed; extern int pic_mode; extern int smp_num_siblings; -extern int cpu_sibling_map[]; +extern cpumask_t cpu_sibling_map[]; -/* - * On x86 all CPUs are mapped 1:1 to the APIC space. - * This simplifies scheduling and IPI sending and - * compresses data structures. - */ -static inline int cpu_logical_map(int cpu) -{ - return cpu; -} -static inline int cpu_number_map(int cpu) -{ - return cpu; -} +extern void smp_flush_tlb(void); +extern void smp_invalidate_rcv(void); /* Process an NMI */ +extern void (*mtrr_hook) (void); +extern void zap_low_mappings (void); -/* - * Some lowlevel functions might want to know about - * the real APIC ID <-> CPU # mapping. - */ #define MAX_APICID 256 -extern volatile int cpu_to_physical_apicid[NR_CPUS]; -extern volatile int physical_apicid_to_cpu[MAX_APICID]; -extern volatile int cpu_to_logical_apicid[NR_CPUS]; -extern volatile int logical_apicid_to_cpu[MAX_APICID]; - -/* - * General functions that each host system must provide. - */ - -/*extern void smp_boot_cpus(void);*/ -extern void smp_store_cpu_info(int id); /* Store per CPU info (like the initial udelay numbers */ +extern u8 x86_cpu_to_apicid[]; /* * This function is needed by all SMP systems. It must _always_ be valid * from the initial startup. We map APIC_BASE very early in page_setup(), * so this is correct in the x86 case. */ +#define __smp_processor_id() (current->processor) -#define smp_processor_id() (current->processor) +extern cpumask_t cpu_callout_map; +extern cpumask_t cpu_callin_map; +#define cpu_possible_map cpu_callout_map -static __inline int hard_smp_processor_id(void) +/* We don't mark CPUs online until __cpu_up(), so we need another measure */ +static inline int num_booting_cpus(void) +{ + return cpus_weight(cpu_callout_map); +} + +extern void map_cpu_to_logical_apicid(void); +extern void unmap_cpu_to_logical_apicid(int cpu); + +#ifdef CONFIG_X86_LOCAL_APIC + +#ifdef APIC_DEFINITION +extern int hard_smp_processor_id(void); +#else +#include +static inline int hard_smp_processor_id(void) { /* we don't want to mark this access volatile - bad code generation */ - return GET_APIC_ID(*(unsigned *)(APIC_BASE+APIC_ID)); + return GET_APIC_ID(*(unsigned int *)(APIC_BASE+APIC_ID)); } +#endif static __inline int logical_smp_processor_id(void) { /* we don't want to mark this access volatile - bad code generation */ - return GET_APIC_LOGICAL_ID(*(unsigned *)(APIC_BASE+APIC_LDR)); + return GET_APIC_LOGICAL_ID(*(unsigned int *)(APIC_BASE+APIC_LDR)); } +#endif #endif /* !__ASSEMBLY__ */ #define NO_PROC_ID 0xFF /* No processor magic marker */ -/* - * This magic constant controls our willingness to transfer - * a process across CPUs. Such a transfer incurs misses on the L1 - * cache, and on a P6 or P5 with multiple L2 caches L2 hits. My - * gut feeling is this will vary by board in value. For a board - * with separate L2 cache it probably depends also on the RSS, and - * for a board with shared L2 cache it ought to decay fast as other - * processes are run. - */ - -#define PROC_CHANGE_PENALTY 15 /* Schedule penalty */ - #endif #endif diff --git a/xen/include/asm-x86/smpboot.h b/xen/include/asm-x86/smpboot.h index 7a0b157114..6def59963b 100644 --- a/xen/include/asm-x86/smpboot.h +++ b/xen/include/asm-x86/smpboot.h @@ -1,132 +1,16 @@ #ifndef __ASM_SMPBOOT_H #define __ASM_SMPBOOT_H -/*emum for clustered_apic_mode values*/ -enum{ - CLUSTERED_APIC_NONE = 0, - CLUSTERED_APIC_XAPIC, - CLUSTERED_APIC_NUMAQ -}; - -#ifdef CONFIG_X86_CLUSTERED_APIC -extern unsigned int apic_broadcast_id; -extern unsigned char clustered_apic_mode; -extern unsigned char esr_disable; -extern unsigned char int_delivery_mode; -extern unsigned int int_dest_addr_mode; -extern int cyclone_setup(char*); - -static inline void detect_clustered_apic(char* oem, char* prod) -{ - /* - * Can't recognize Summit xAPICs at present, so use the OEM ID. - */ - if (!strncmp(oem, "IBM ENSW", 8) && !strncmp(prod, "VIGIL SMP", 9)){ - clustered_apic_mode = CLUSTERED_APIC_XAPIC; - apic_broadcast_id = APIC_BROADCAST_ID_XAPIC; - int_dest_addr_mode = APIC_DEST_PHYSICAL; - int_delivery_mode = dest_Fixed; - esr_disable = 1; - /*Start cyclone clock*/ - cyclone_setup(0); - /* check for ACPI tables */ - } else if (!strncmp(oem, "IBM", 3) && - (!strncmp(prod, "SERVIGIL", 8) || - !strncmp(prod, "EXA", 3) || - !strncmp(prod, "RUTHLESS", 8))){ - clustered_apic_mode = CLUSTERED_APIC_XAPIC; - apic_broadcast_id = APIC_BROADCAST_ID_XAPIC; - int_dest_addr_mode = APIC_DEST_PHYSICAL; - int_delivery_mode = dest_Fixed; - esr_disable = 1; - /*Start cyclone clock*/ - cyclone_setup(0); - } else if (!strncmp(oem, "IBM NUMA", 8)){ - clustered_apic_mode = CLUSTERED_APIC_NUMAQ; - apic_broadcast_id = APIC_BROADCAST_ID_APIC; - int_dest_addr_mode = APIC_DEST_LOGICAL; - int_delivery_mode = dest_LowestPrio; - esr_disable = 1; - } -} -#define INT_DEST_ADDR_MODE (int_dest_addr_mode) -#define INT_DELIVERY_MODE (int_delivery_mode) -#else /* CONFIG_X86_CLUSTERED_APIC */ -#define apic_broadcast_id (APIC_BROADCAST_ID_APIC) -#define clustered_apic_mode (CLUSTERED_APIC_NONE) -#define esr_disable (0) -#define detect_clustered_apic(x,y) -#define INT_DEST_ADDR_MODE (APIC_DEST_LOGICAL) /* logical delivery */ -#define INT_DELIVERY_MODE (dest_LowestPrio) -#endif /* CONFIG_X86_CLUSTERED_APIC */ -#define BAD_APICID 0xFFu - -#define TRAMPOLINE_LOW phys_to_virt((clustered_apic_mode == CLUSTERED_APIC_NUMAQ)?0x8:0x467) -#define TRAMPOLINE_HIGH phys_to_virt((clustered_apic_mode == CLUSTERED_APIC_NUMAQ)?0xa:0x469) - -#define boot_cpu_apicid ((clustered_apic_mode == CLUSTERED_APIC_NUMAQ)?boot_cpu_logical_apicid:boot_cpu_physical_apicid) - -extern unsigned char raw_phys_apicid[NR_CPUS]; - -/* - * How to map from the cpu_present_map - */ -static inline int cpu_present_to_apicid(int mps_cpu) -{ - if (clustered_apic_mode == CLUSTERED_APIC_XAPIC) - return raw_phys_apicid[mps_cpu]; - if(clustered_apic_mode == CLUSTERED_APIC_NUMAQ) - return (mps_cpu/4)*16 + (1<<(mps_cpu%4)); - return mps_cpu; -} - static inline unsigned long apicid_to_phys_cpu_present(int apicid) { - if(clustered_apic_mode) - return 1UL << (((apicid >> 4) << 2) + (apicid & 0x3)); return 1UL << apicid; } -#define physical_to_logical_apicid(phys_apic) ( (1ul << (phys_apic & 0x3)) | (phys_apic & 0xF0u) ) - -/* - * Mappings between logical cpu number and logical / physical apicid - * The first four macros are trivial, but it keeps the abstraction consistent - */ extern volatile int logical_apicid_2_cpu[]; extern volatile int cpu_2_logical_apicid[]; extern volatile int physical_apicid_2_cpu[]; extern volatile int cpu_2_physical_apicid[]; -#define logical_apicid_to_cpu(apicid) logical_apicid_2_cpu[apicid] -#define cpu_to_logical_apicid(cpu) cpu_2_logical_apicid[cpu] -#define physical_apicid_to_cpu(apicid) physical_apicid_2_cpu[apicid] -#define cpu_to_physical_apicid(cpu) cpu_2_physical_apicid[cpu] -#ifdef CONFIG_MULTIQUAD /* use logical IDs to bootstrap */ -#define boot_apicid_to_cpu(apicid) logical_apicid_2_cpu[apicid] -#define cpu_to_boot_apicid(cpu) cpu_2_logical_apicid[cpu] -#else /* !CONFIG_MULTIQUAD */ /* use physical IDs to bootstrap */ #define boot_apicid_to_cpu(apicid) physical_apicid_2_cpu[apicid] -#define cpu_to_boot_apicid(cpu) cpu_2_physical_apicid[cpu] -#endif /* CONFIG_MULTIQUAD */ -#ifdef CONFIG_X86_CLUSTERED_APIC -static inline int target_cpus(void) -{ - static int cpu; - switch(clustered_apic_mode){ - case CLUSTERED_APIC_NUMAQ: - /* Broadcast intrs to local quad only. */ - return APIC_BROADCAST_ID_APIC; - case CLUSTERED_APIC_XAPIC: - /*round robin the interrupts*/ - cpu = (cpu+1)%smp_num_cpus; - return cpu_to_physical_apicid(cpu); - default: - } - return cpu_online_map; -} -#else -#define target_cpus() (cpu_online_map) -#endif #endif diff --git a/xen/include/asm-x86/system.h b/xen/include/asm-x86/system.h index 49355af7d6..cd0619008d 100644 --- a/xen/include/asm-x86/system.h +++ b/xen/include/asm-x86/system.h @@ -112,6 +112,7 @@ static always_inline unsigned long __cmpxchg(volatile void *ptr, unsigned long o return old; } +#define __HAVE_ARCH_CMPXCHG #define cmpxchg(ptr,o,n)\ ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\ (unsigned long)(n),sizeof(*(ptr)))) diff --git a/xen/include/asm-x86/time.h b/xen/include/asm-x86/time.h index 2256145bec..8f48cd31dc 100644 --- a/xen/include/asm-x86/time.h +++ b/xen/include/asm-x86/time.h @@ -2,6 +2,6 @@ #ifndef __X86_TIME_H__ #define __X86_TIME_H__ -/* nothing */ +extern int timer_ack; #endif /* __X86_TIME_H__ */ diff --git a/xen/include/xen/acpi.h b/xen/include/xen/acpi.h index feda09036a..b84f047651 100644 --- a/xen/include/xen/acpi.h +++ b/xen/include/xen/acpi.h @@ -80,7 +80,7 @@ typedef struct { struct acpi_table_rsdt { struct acpi_table_header header; - u32 entry[1]; + u32 entry[8]; } __attribute__ ((packed)); /* Extended System Description Table (XSDT) */ @@ -232,9 +232,28 @@ struct acpi_table_hpet { u8 page_protect; } __attribute__ ((packed)); +/* + * Simple Boot Flags + * http://www.microsoft.com/whdc/hwdev/resources/specs/simp_bios.mspx + */ +struct acpi_table_sbf +{ + u8 sbf_signature[4]; + u32 sbf_len; + u8 sbf_revision; + u8 sbf_csum; + u8 sbf_oemid[6]; + u8 sbf_oemtable[8]; + u8 sbf_revdata[4]; + u8 sbf_creator[4]; + u8 sbf_crearev[4]; + u8 sbf_cmos; + u8 sbf_spare[3]; +} __attribute__ ((packed)); + /* * System Resource Affinity Table (SRAT) - * see http://www.microsoft.com/hwdev/design/srat.htm + * http://www.microsoft.com/whdc/hwdev/platform/proc/SRAT.mspx */ struct acpi_table_srat { @@ -309,7 +328,7 @@ struct acpi_table_sbst { /* Embedded Controller Boot Resources Table (ECDT) */ struct acpi_table_ecdt { - struct acpi_table_header header; + struct acpi_table_header header; struct acpi_generic_address ec_control; struct acpi_generic_address ec_data; u32 uid; @@ -317,6 +336,15 @@ struct acpi_table_ecdt { char ec_id[0]; } __attribute__ ((packed)); +/* PCI MMCONFIG */ + +struct acpi_table_mcfg { + struct acpi_table_header header; + u8 reserved[8]; + u32 base_address; + u32 base_reserved; +} __attribute__ ((packed)); + /* Table Handlers */ enum acpi_table_id { @@ -338,6 +366,7 @@ enum acpi_table_id { ACPI_SSDT, ACPI_SPMI, ACPI_HPET, + ACPI_MCFG, ACPI_TABLE_COUNT }; @@ -345,18 +374,19 @@ typedef int (*acpi_table_handler) (unsigned long phys_addr, unsigned long size); extern acpi_table_handler acpi_table_ops[ACPI_TABLE_COUNT]; -typedef int (*acpi_madt_entry_handler) (acpi_table_entry_header *header); +typedef int (*acpi_madt_entry_handler) (acpi_table_entry_header *header, const unsigned long end); char * __acpi_map_table (unsigned long phys_addr, unsigned long size); unsigned long acpi_find_rsdp (void); int acpi_boot_init (void); +int acpi_boot_table_init (void); int acpi_numa_init (void); int acpi_table_init (void); int acpi_table_parse (enum acpi_table_id id, acpi_table_handler handler); int acpi_get_table_header_early (enum acpi_table_id id, struct acpi_table_header **header); -int acpi_table_parse_madt (enum acpi_madt_entry_id id, acpi_madt_entry_handler handler); -int acpi_table_parse_srat (enum acpi_srat_entry_id id, acpi_madt_entry_handler handler); +int acpi_table_parse_madt (enum acpi_madt_entry_id id, acpi_madt_entry_handler handler, unsigned int max_entries); +int acpi_table_parse_srat (enum acpi_srat_entry_id id, acpi_madt_entry_handler handler, unsigned int max_entries); void acpi_table_print (struct acpi_table_header *header, unsigned long phys_addr); void acpi_table_print_madt_entry (acpi_table_entry_header *madt); void acpi_table_print_srat_entry (acpi_table_entry_header *srat); @@ -367,15 +397,45 @@ void acpi_numa_processor_affinity_init (struct acpi_table_processor_affinity *pa void acpi_numa_memory_affinity_init (struct acpi_table_memory_affinity *ma); void acpi_numa_arch_fixup(void); -#else /*!CONFIG_ACPI_BOOT*/ +#ifdef CONFIG_ACPI_HOTPLUG_CPU +/* Arch dependent functions for cpu hotplug support */ +int acpi_map_lsapic(acpi_handle handle, int *pcpu); +int acpi_unmap_lsapic(int cpu); +#endif /* CONFIG_ACPI_HOTPLUG_CPU */ + +extern int acpi_mp_config; + +extern u32 pci_mmcfg_base_addr; + +extern int sbf_port ; + +#else /*!CONFIG_ACPI_BOOT*/ + +#define acpi_mp_config 0 static inline int acpi_boot_init(void) { return 0; } -#endif /*!CONFIG_ACPI_BOOT*/ +static inline int acpi_boot_table_init(void) +{ + return 0; +} + +#endif /*!CONFIG_ACPI_BOOT*/ +unsigned int acpi_register_gsi (u32 gsi, int edge_level, int active_high_low); +int acpi_gsi_to_irq (u32 gsi, unsigned int *irq); + +/* + * This function undoes the effect of one call to acpi_register_gsi(). + * If this matches the last registration, any IRQ resources for gsi + * are freed. + */ +#ifdef CONFIG_ACPI_DEALLOCATE_IRQ +void acpi_unregister_gsi (u32 gsi); +#endif #ifdef CONFIG_ACPI_PCI @@ -400,7 +460,11 @@ extern struct acpi_prt_list acpi_prt; struct pci_dev; int acpi_pci_irq_enable (struct pci_dev *dev); -int acpi_pci_irq_init (void); +void acpi_penalize_isa_irq(int irq); + +#ifdef CONFIG_ACPI_DEALLOCATE_IRQ +void acpi_pci_irq_disable (struct pci_dev *dev); +#endif struct acpi_pci_driver { struct acpi_pci_driver *next; @@ -415,14 +479,15 @@ void acpi_pci_unregister_driver(struct acpi_pci_driver *driver); #ifdef CONFIG_ACPI_EC -int ec_read(u8 addr, u8 *val); -int ec_write(u8 addr, u8 val); +extern int ec_read(u8 addr, u8 *val); +extern int ec_write(u8 addr, u8 val); #endif /*CONFIG_ACPI_EC*/ #ifdef CONFIG_ACPI_INTERPRETER -int acpi_blacklisted(void); +extern int acpi_blacklisted(void); +extern void acpi_bios_year(char *s); #else /*!CONFIG_ACPI_INTERPRETER*/ @@ -433,4 +498,41 @@ static inline int acpi_blacklisted(void) #endif /*!CONFIG_ACPI_INTERPRETER*/ +#define ACPI_CSTATE_LIMIT_DEFINED /* for driver builds */ +#ifdef CONFIG_ACPI + +/* + * Set highest legal C-state + * 0: C0 okay, but not C1 + * 1: C1 okay, but not C2 + * 2: C2 okay, but not C3 etc. + */ + +extern unsigned int max_cstate; + +static inline unsigned int acpi_get_cstate_limit(void) +{ + return max_cstate; +} +static inline void acpi_set_cstate_limit(unsigned int new_limit) +{ + max_cstate = new_limit; + return; +} +#else +static inline unsigned int acpi_get_cstate_limit(void) { return 0; } +static inline void acpi_set_cstate_limit(unsigned int new_limit) { return; } +#endif + +#ifdef CONFIG_ACPI_NUMA +int acpi_get_pxm(acpi_handle handle); +#else +static inline int acpi_get_pxm(acpi_handle handle) +{ + return 0; +} +#endif + +extern int pnpacpi_disabled; + #endif /*_LINUX_ACPI_H*/ diff --git a/xen/include/xen/bitmap.h b/xen/include/xen/bitmap.h new file mode 100644 index 0000000000..c91a10aef0 --- /dev/null +++ b/xen/include/xen/bitmap.h @@ -0,0 +1,249 @@ +#ifndef __XEN_BITMAP_H +#define __XEN_BITMAP_H + +#ifndef __ASSEMBLY__ + +#include +#include +#include + +/* + * bitmaps provide bit arrays that consume one or more unsigned + * longs. The bitmap interface and available operations are listed + * here, in bitmap.h + * + * Function implementations generic to all architectures are in + * lib/bitmap.c. Functions implementations that are architecture + * specific are in various include/asm-/bitops.h headers + * and other arch/ specific files. + * + * See lib/bitmap.c for more details. + */ + +/* + * The available bitmap operations and their rough meaning in the + * case that the bitmap is a single unsigned long are thus: + * + * bitmap_zero(dst, nbits) *dst = 0UL + * bitmap_fill(dst, nbits) *dst = ~0UL + * bitmap_copy(dst, src, nbits) *dst = *src + * bitmap_and(dst, src1, src2, nbits) *dst = *src1 & *src2 + * bitmap_or(dst, src1, src2, nbits) *dst = *src1 | *src2 + * bitmap_xor(dst, src1, src2, nbits) *dst = *src1 ^ *src2 + * bitmap_andnot(dst, src1, src2, nbits) *dst = *src1 & ~(*src2) + * bitmap_complement(dst, src, nbits) *dst = ~(*src) + * bitmap_equal(src1, src2, nbits) Are *src1 and *src2 equal? + * bitmap_intersects(src1, src2, nbits) Do *src1 and *src2 overlap? + * bitmap_subset(src1, src2, nbits) Is *src1 a subset of *src2? + * bitmap_empty(src, nbits) Are all bits zero in *src? + * bitmap_full(src, nbits) Are all bits set in *src? + * bitmap_weight(src, nbits) Hamming Weight: number set bits + * bitmap_shift_right(dst, src, n, nbits) *dst = *src >> n + * bitmap_shift_left(dst, src, n, nbits) *dst = *src << n + */ + +/* + * Also the following operations in asm/bitops.h apply to bitmaps. + * + * set_bit(bit, addr) *addr |= bit + * clear_bit(bit, addr) *addr &= ~bit + * change_bit(bit, addr) *addr ^= bit + * test_bit(bit, addr) Is bit set in *addr? + * test_and_set_bit(bit, addr) Set bit and return old value + * test_and_clear_bit(bit, addr) Clear bit and return old value + * test_and_change_bit(bit, addr) Change bit and return old value + * find_first_zero_bit(addr, nbits) Position first zero bit in *addr + * find_first_bit(addr, nbits) Position first set bit in *addr + * find_next_zero_bit(addr, nbits, bit) Position next zero bit in *addr >= bit + * find_next_bit(addr, nbits, bit) Position next set bit in *addr >= bit + */ + +/* + * The DECLARE_BITMAP(name,bits) macro, in xen/types.h, can be used + * to declare an array named 'name' of just enough unsigned longs to + * contain all bit positions from 0 to 'bits' - 1. + */ + +/* + * lib/bitmap.c provides these functions: + */ + +extern int __bitmap_empty(const unsigned long *bitmap, int bits); +extern int __bitmap_full(const unsigned long *bitmap, int bits); +extern int __bitmap_equal(const unsigned long *bitmap1, + const unsigned long *bitmap2, int bits); +extern void __bitmap_complement(unsigned long *dst, const unsigned long *src, + int bits); +extern void __bitmap_shift_right(unsigned long *dst, + const unsigned long *src, int shift, int bits); +extern void __bitmap_shift_left(unsigned long *dst, + const unsigned long *src, int shift, int bits); +extern void __bitmap_and(unsigned long *dst, const unsigned long *bitmap1, + const unsigned long *bitmap2, int bits); +extern void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1, + const unsigned long *bitmap2, int bits); +extern void __bitmap_xor(unsigned long *dst, const unsigned long *bitmap1, + const unsigned long *bitmap2, int bits); +extern void __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1, + const unsigned long *bitmap2, int bits); +extern int __bitmap_intersects(const unsigned long *bitmap1, + const unsigned long *bitmap2, int bits); +extern int __bitmap_subset(const unsigned long *bitmap1, + const unsigned long *bitmap2, int bits); +extern int __bitmap_weight(const unsigned long *bitmap, int bits); + +extern int bitmap_find_free_region(unsigned long *bitmap, int bits, int order); +extern void bitmap_release_region(unsigned long *bitmap, int pos, int order); +extern int bitmap_allocate_region(unsigned long *bitmap, int pos, int order); + +#define BITMAP_LAST_WORD_MASK(nbits) \ +( \ + ((nbits) % BITS_PER_LONG) ? \ + (1UL<<((nbits) % BITS_PER_LONG))-1 : ~0UL \ +) + +static inline void bitmap_zero(unsigned long *dst, int nbits) +{ + if (nbits <= BITS_PER_LONG) + *dst = 0UL; + else { + int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long); + memset(dst, 0, len); + } +} + +static inline void bitmap_fill(unsigned long *dst, int nbits) +{ + size_t nlongs = BITS_TO_LONGS(nbits); + if (nlongs > 1) { + int len = (nlongs - 1) * sizeof(unsigned long); + memset(dst, 0xff, len); + } + dst[nlongs - 1] = BITMAP_LAST_WORD_MASK(nbits); +} + +static inline void bitmap_copy(unsigned long *dst, const unsigned long *src, + int nbits) +{ + if (nbits <= BITS_PER_LONG) + *dst = *src; + else { + int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long); + memcpy(dst, src, len); + } +} + +static inline void bitmap_and(unsigned long *dst, const unsigned long *src1, + const unsigned long *src2, int nbits) +{ + if (nbits <= BITS_PER_LONG) + *dst = *src1 & *src2; + else + __bitmap_and(dst, src1, src2, nbits); +} + +static inline void bitmap_or(unsigned long *dst, const unsigned long *src1, + const unsigned long *src2, int nbits) +{ + if (nbits <= BITS_PER_LONG) + *dst = *src1 | *src2; + else + __bitmap_or(dst, src1, src2, nbits); +} + +static inline void bitmap_xor(unsigned long *dst, const unsigned long *src1, + const unsigned long *src2, int nbits) +{ + if (nbits <= BITS_PER_LONG) + *dst = *src1 ^ *src2; + else + __bitmap_xor(dst, src1, src2, nbits); +} + +static inline void bitmap_andnot(unsigned long *dst, const unsigned long *src1, + const unsigned long *src2, int nbits) +{ + if (nbits <= BITS_PER_LONG) + *dst = *src1 & ~(*src2); + else + __bitmap_andnot(dst, src1, src2, nbits); +} + +static inline void bitmap_complement(unsigned long *dst, const unsigned long *src, + int nbits) +{ + if (nbits <= BITS_PER_LONG) + *dst = ~(*src) & BITMAP_LAST_WORD_MASK(nbits); + else + __bitmap_complement(dst, src, nbits); +} + +static inline int bitmap_equal(const unsigned long *src1, + const unsigned long *src2, int nbits) +{ + if (nbits <= BITS_PER_LONG) + return ! ((*src1 ^ *src2) & BITMAP_LAST_WORD_MASK(nbits)); + else + return __bitmap_equal(src1, src2, nbits); +} + +static inline int bitmap_intersects(const unsigned long *src1, + const unsigned long *src2, int nbits) +{ + if (nbits <= BITS_PER_LONG) + return ((*src1 & *src2) & BITMAP_LAST_WORD_MASK(nbits)) != 0; + else + return __bitmap_intersects(src1, src2, nbits); +} + +static inline int bitmap_subset(const unsigned long *src1, + const unsigned long *src2, int nbits) +{ + if (nbits <= BITS_PER_LONG) + return ! ((*src1 & ~(*src2)) & BITMAP_LAST_WORD_MASK(nbits)); + else + return __bitmap_subset(src1, src2, nbits); +} + +static inline int bitmap_empty(const unsigned long *src, int nbits) +{ + if (nbits <= BITS_PER_LONG) + return ! (*src & BITMAP_LAST_WORD_MASK(nbits)); + else + return __bitmap_empty(src, nbits); +} + +static inline int bitmap_full(const unsigned long *src, int nbits) +{ + if (nbits <= BITS_PER_LONG) + return ! (~(*src) & BITMAP_LAST_WORD_MASK(nbits)); + else + return __bitmap_full(src, nbits); +} + +static inline int bitmap_weight(const unsigned long *src, int nbits) +{ + return __bitmap_weight(src, nbits); +} + +static inline void bitmap_shift_right(unsigned long *dst, + const unsigned long *src, int n, int nbits) +{ + if (nbits <= BITS_PER_LONG) + *dst = *src >> n; + else + __bitmap_shift_right(dst, src, n, nbits); +} + +static inline void bitmap_shift_left(unsigned long *dst, + const unsigned long *src, int n, int nbits) +{ + if (nbits <= BITS_PER_LONG) + *dst = (*src << n) & BITMAP_LAST_WORD_MASK(nbits); + else + __bitmap_shift_left(dst, src, n, nbits); +} + +#endif /* __ASSEMBLY__ */ + +#endif /* __XEN_BITMAP_H */ diff --git a/xen/include/xen/bitops.h b/xen/include/xen/bitops.h new file mode 100644 index 0000000000..e743c0059d --- /dev/null +++ b/xen/include/xen/bitops.h @@ -0,0 +1,129 @@ +#ifndef _LINUX_BITOPS_H +#define _LINUX_BITOPS_H +#include + +/* + * ffs: find first bit set. This is defined the same way as + * the libc and compiler builtin ffs routines, therefore + * differs in spirit from the above ffz (man ffs). + */ + +static inline int generic_ffs(int x) +{ + int r = 1; + + if (!x) + return 0; + if (!(x & 0xffff)) { + x >>= 16; + r += 16; + } + if (!(x & 0xff)) { + x >>= 8; + r += 8; + } + if (!(x & 0xf)) { + x >>= 4; + r += 4; + } + if (!(x & 3)) { + x >>= 2; + r += 2; + } + if (!(x & 1)) { + x >>= 1; + r += 1; + } + return r; +} + +/* + * fls: find last bit set. + */ + +static __inline__ int generic_fls(int x) +{ + int r = 32; + + if (!x) + return 0; + if (!(x & 0xffff0000u)) { + x <<= 16; + r -= 16; + } + if (!(x & 0xff000000u)) { + x <<= 8; + r -= 8; + } + if (!(x & 0xf0000000u)) { + x <<= 4; + r -= 4; + } + if (!(x & 0xc0000000u)) { + x <<= 2; + r -= 2; + } + if (!(x & 0x80000000u)) { + x <<= 1; + r -= 1; + } + return r; +} + +/* + * Include this here because some architectures need generic_ffs/fls in + * scope + */ +#include + +/* + * hweightN: returns the hamming weight (i.e. the number + * of bits set) of a N-bit word + */ + +static inline unsigned int generic_hweight32(unsigned int w) +{ + unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555); + res = (res & 0x33333333) + ((res >> 2) & 0x33333333); + res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F); + res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF); + return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF); +} + +static inline unsigned int generic_hweight16(unsigned int w) +{ + unsigned int res = (w & 0x5555) + ((w >> 1) & 0x5555); + res = (res & 0x3333) + ((res >> 2) & 0x3333); + res = (res & 0x0F0F) + ((res >> 4) & 0x0F0F); + return (res & 0x00FF) + ((res >> 8) & 0x00FF); +} + +static inline unsigned int generic_hweight8(unsigned int w) +{ + unsigned int res = (w & 0x55) + ((w >> 1) & 0x55); + res = (res & 0x33) + ((res >> 2) & 0x33); + return (res & 0x0F) + ((res >> 4) & 0x0F); +} + +static inline unsigned long generic_hweight64(__u64 w) +{ +#if BITS_PER_LONG < 64 + return generic_hweight32((unsigned int)(w >> 32)) + + generic_hweight32((unsigned int)w); +#else + u64 res; + res = (w & 0x5555555555555555ul) + ((w >> 1) & 0x5555555555555555ul); + res = (res & 0x3333333333333333ul) + ((res >> 2) & 0x3333333333333333ul); + res = (res & 0x0F0F0F0F0F0F0F0Ful) + ((res >> 4) & 0x0F0F0F0F0F0F0F0Ful); + res = (res & 0x00FF00FF00FF00FFul) + ((res >> 8) & 0x00FF00FF00FF00FFul); + res = (res & 0x0000FFFF0000FFFFul) + ((res >> 16) & 0x0000FFFF0000FFFFul); + return (res & 0x00000000FFFFFFFFul) + ((res >> 32) & 0x00000000FFFFFFFFul); +#endif +} + +static inline unsigned long hweight_long(unsigned long w) +{ + return sizeof(w) == 4 ? generic_hweight32(w) : generic_hweight64(w); +} + +#endif diff --git a/xen/include/xen/config.h b/xen/include/xen/config.h index 95101174ba..ca3650f80f 100644 --- a/xen/include/xen/config.h +++ b/xen/include/xen/config.h @@ -15,7 +15,7 @@ #define always_inline __inline__ __attribute__ ((always_inline)) -/* syslog levels ==> nothing! */ +/* Linux syslog levels. */ #define KERN_NOTICE "" #define KERN_WARNING "" #define KERN_DEBUG "" @@ -25,6 +25,10 @@ #define KERN_EMERG "" #define KERN_ALERT "" +/* Linux 'checker' project. */ +#define __iomem +#define __user + #ifdef VERBOSE #define DPRINTK(_f, _a...) printk("(file=%s, line=%d) " _f, \ __FILE__ , __LINE__ , ## _a ) diff --git a/xen/include/xen/cpumask.h b/xen/include/xen/cpumask.h new file mode 100644 index 0000000000..33723fbd9a --- /dev/null +++ b/xen/include/xen/cpumask.h @@ -0,0 +1,25 @@ +/* + * XXX This to be replaced with the Linux file in the near future. + */ + +#ifndef __XEN_CPUMASK_H__ +#define __XEN_CPUMASK_H__ + +#include + +typedef u32 cpumask_t; + +extern cpumask_t cpu_online_map; + +static inline int cpus_weight(cpumask_t w) +{ + unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555); + res = (res & 0x33333333) + ((res >> 2) & 0x33333333); + res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F); + res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF); + return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF); +} + +#define cpus_addr(_m) (&(_m)) + +#endif /* __XEN_CPUMASK_H__ */ diff --git a/xen/include/xen/irq.h b/xen/include/xen/irq.h index 6c77460f41..f419f0c182 100644 --- a/xen/include/xen/irq.h +++ b/xen/include/xen/irq.h @@ -2,6 +2,7 @@ #define __XEN_IRQ_H__ #include +#include #include #include #include @@ -35,7 +36,7 @@ struct hw_interrupt_type { void (*disable)(unsigned int irq); void (*ack)(unsigned int irq); void (*end)(unsigned int irq); - void (*set_affinity)(unsigned int irq, unsigned long mask); + void (*set_affinity)(unsigned int irq, cpumask_t mask); }; typedef struct hw_interrupt_type hw_irq_controller; diff --git a/xen/include/xen/smp.h b/xen/include/xen/smp.h index df80e23295..811e25ac24 100644 --- a/xen/include/xen/smp.h +++ b/xen/include/xen/smp.h @@ -46,6 +46,17 @@ extern void smp_commence(void); extern int smp_call_function( void (*func) (void *info), void *info, int retry, int wait); +/* + * Call a function on all processors + */ +static inline int on_each_cpu(void (*func) (void *info), void *info, + int retry, int wait) +{ + int ret = smp_call_function(func, info, retry, wait); + func(info); + return ret; +} + /* * True once the per process idle is forked */ @@ -85,7 +96,15 @@ extern volatile int smp_msg_id; #define cpu_logical_map(cpu) 0 #define cpu_number_map(cpu) 0 #define smp_call_function(func,info,retry,wait) 0 +#define on_each_cpu(func,info,retry,wait) ({ func(info); 0; }) #define cpu_online_map 1 #endif + +#ifdef __smp_processor_id +#define smp_processor_id() __smp_processor_id() +#else +extern unsigned int smp_processor_id(void); +#endif + #endif diff --git a/xen/include/xen/spinlock.h b/xen/include/xen/spinlock.h index ef58ba591b..73184daad8 100644 --- a/xen/include/xen/spinlock.h +++ b/xen/include/xen/spinlock.h @@ -82,4 +82,7 @@ typedef struct { int gcc_is_buggy; } rwlock_t; #define write_lock(_lock) _raw_write_lock(_lock) #define write_unlock(_lock) _raw_write_unlock(_lock) +#define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED +#define DEFINE_RWLOCK(x) rwlock_t x = RW_LOCK_UNLOCKED + #endif /* __SPINLOCK_H__ */ diff --git a/xen/include/xen/types.h b/xen/include/xen/types.h index cd55353dfe..6258a745cf 100644 --- a/xen/include/xen/types.h +++ b/xen/include/xen/types.h @@ -1,8 +1,14 @@ #ifndef __TYPES_H__ #define __TYPES_H__ +#include #include +#define BITS_TO_LONGS(bits) \ + (((bits)+BITS_PER_LONG-1)/BITS_PER_LONG) +#define DECLARE_BITMAP(name,bits) \ + unsigned long name[BITS_TO_LONGS(bits)] + #ifndef NULL #define NULL ((void*)0) #endif -- 2.30.2